1 /* $OpenBSD: portmap.c,v 1.41 2010/09/01 14:43:34 millert 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 * Copyright (c) 2010, Oracle America, Inc. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions are 37 * met: 38 * 39 * * Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * * Redistributions in binary form must reproduce the above 42 * copyright notice, this list of conditions and the following 43 * disclaimer in the documentation and/or other materials 44 * provided with the distribution. 45 * * Neither the name of the "Oracle America, Inc." nor the names of its 46 * contributors may be used to endorse or promote products derived 47 * from this software without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 52 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 53 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 54 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 56 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 58 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 59 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 /* 64 * portmap.c, Implements the program,version to port number mapping for 65 * rpc. 66 */ 67 68 #include <sys/types.h> 69 #include <sys/socket.h> 70 #include <sys/ioctl.h> 71 #include <sys/wait.h> 72 #include <sys/resource.h> 73 74 #include <rpcsvc/nfs_prot.h> 75 #include <arpa/inet.h> 76 #include <rpc/rpc.h> 77 #include <rpc/pmap_prot.h> 78 79 #include <signal.h> 80 #include <stdio.h> 81 #include <stdlib.h> 82 #include <string.h> 83 #include <syslog.h> 84 #include <unistd.h> 85 #include <netdb.h> 86 #include <pwd.h> 87 #include <errno.h> 88 89 void reg_service(struct svc_req *, SVCXPRT *); 90 void reap(int); 91 void callit(struct svc_req *, SVCXPRT *); 92 int check_callit(struct sockaddr_in *, u_long, u_long); 93 struct pmaplist *find_service(u_long, u_long, u_long); 94 95 struct pmaplist *pmaplist; 96 int debugging; 97 98 SVCXPRT *ludpxprt, *ltcpxprt; 99 100 int 101 main(int argc, char *argv[]) 102 { 103 int sock, lsock, c, on = 1; 104 socklen_t len = sizeof(struct sockaddr_in); 105 struct sockaddr_in addr, laddr; 106 struct pmaplist *pml; 107 struct passwd *pw; 108 SVCXPRT *xprt; 109 110 while ((c = getopt(argc, argv, "d")) != -1) { 111 switch (c) { 112 case 'd': 113 debugging = 1; 114 break; 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 : 127 LOG_PID), LOG_DAEMON); 128 129 bzero(&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(&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)) == 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)) == NULL) { 167 syslog(LOG_ERR, "couldn't do udp_create"); 168 exit(1); 169 } 170 171 /* make an entry for ourself */ 172 pml = malloc(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 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)) == NULL) { 210 syslog(LOG_ERR, "couldn't do tcp_create"); 211 exit(1); 212 } 213 214 /* make an entry for ourself */ 215 pml = malloc(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 if ((pw = getpwnam("_portmap")) == NULL) { 228 syslog(LOG_ERR, "no such user _portmap"); 229 exit(1); 230 } 231 if (chroot("/var/empty") == -1) { 232 syslog(LOG_ERR, "cannot chroot to /var/empty."); 233 exit(1); 234 } 235 if (chdir("/") == -1) { 236 syslog(LOG_ERR, "cannot chdir to new /."); 237 exit(1); 238 } 239 240 if (pw) { 241 if (setgroups(1, &pw->pw_gid) == -1 || 242 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || 243 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { 244 syslog(LOG_ERR, "revoke privs: %s", strerror(errno)); 245 exit(1); 246 } 247 } 248 endpwent(); 249 250 if (svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE) == 0) { 251 syslog(LOG_ERR, "svc_register failed."); 252 exit(1); 253 } 254 255 (void)signal(SIGCHLD, reap); 256 svc_run(); 257 syslog(LOG_ERR, "svc_run returned unexpectedly"); 258 abort(); 259 } 260 261 #ifndef lint 262 /* need to override perror calls in rpc library */ 263 void 264 perror(const char *what) 265 { 266 267 syslog(LOG_ERR, "%s: %m", what); 268 } 269 #endif 270 271 struct pmaplist * 272 find_service(u_long prog, u_long vers, u_long prot) 273 { 274 struct pmaplist *hit = NULL; 275 struct pmaplist *pml; 276 277 for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { 278 if ((pml->pml_map.pm_prog != prog) || 279 (pml->pml_map.pm_prot != prot)) 280 continue; 281 hit = pml; 282 if (pml->pml_map.pm_vers == vers) 283 break; 284 } 285 return (hit); 286 } 287 288 /* 289 * 1 OK, 0 not 290 */ 291 void 292 reg_service(struct svc_req *rqstp, SVCXPRT *xprt) 293 { 294 struct pmap reg; 295 struct pmaplist *pml, *prevpml, *fnd; 296 struct sockaddr_in *fromsin; 297 long ans = 0, port; 298 void *t; 299 300 fromsin = svc_getcaller(xprt); 301 302 if (debugging) 303 (void)fprintf(stderr, "server: about to do a switch\n"); 304 switch (rqstp->rq_proc) { 305 case PMAPPROC_NULL: 306 /* 307 * Null proc call 308 */ 309 if (!svc_sendreply(xprt, xdr_void, NULL) && debugging) { 310 abort(); 311 } 312 break; 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 = 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 case PMAPPROC_UNSET: 389 /* 390 * Remove a program,version to port mapping. 391 */ 392 if (xprt != ltcpxprt && xprt != ludpxprt) { 393 syslog(LOG_WARNING, 394 "non-local unset attempt (might be from %s)", 395 inet_ntoa(fromsin->sin_addr)); 396 svcerr_noproc(xprt); 397 return; 398 } 399 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 400 svcerr_decode(xprt); 401 break; 402 } 403 for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { 404 if ((pml->pml_map.pm_prog != reg.pm_prog) || 405 (pml->pml_map.pm_vers != reg.pm_vers)) { 406 /* both pml & prevpml move forwards */ 407 prevpml = pml; 408 pml = pml->pml_next; 409 continue; 410 } 411 if ((pml->pml_map.pm_port < IPPORT_RESERVED || 412 pml->pml_map.pm_port == NFS_PORT) && 413 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 414 syslog(LOG_WARNING, 415 "resvport unset attempt by non-root"); 416 break; 417 } 418 419 /* found it; pml moves forward, prevpml stays */ 420 ans = 1; 421 t = pml; 422 pml = pml->pml_next; 423 if (prevpml == NULL) 424 pmaplist = pml; 425 else 426 prevpml->pml_next = pml; 427 free(t); 428 } 429 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 430 debugging) { 431 fprintf(stderr, "svc_sendreply\n"); 432 abort(); 433 } 434 break; 435 case PMAPPROC_GETPORT: 436 /* 437 * Lookup the mapping for a program,version and return its port 438 */ 439 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 440 svcerr_decode(xprt); 441 break; 442 } 443 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 444 if (fnd) 445 port = fnd->pml_map.pm_port; 446 else 447 port = 0; 448 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && 449 debugging) { 450 fprintf(stderr, "svc_sendreply\n"); 451 abort(); 452 } 453 break; 454 case PMAPPROC_DUMP: 455 /* 456 * Return the current set of mapped program,version 457 */ 458 if (!svc_getargs(xprt, xdr_void, NULL)) { 459 svcerr_decode(xprt); 460 break; 461 } 462 if (!svc_sendreply(xprt, xdr_pmaplist, (caddr_t)&pmaplist) && 463 debugging) { 464 fprintf(stderr, "svc_sendreply\n"); 465 abort(); 466 } 467 break; 468 case PMAPPROC_CALLIT: 469 /* 470 * Calls a procedure on the local machine. If the requested 471 * procedure is not registered this procedure does not return 472 * error information!! 473 * This procedure is only supported on rpc/udp and calls via 474 * rpc/udp. It passes null authentication parameters. 475 */ 476 callit(rqstp, xprt); 477 break; 478 default: 479 svcerr_noproc(xprt); 480 break; 481 } 482 } 483 484 485 /* 486 * Stuff for the rmtcall service 487 */ 488 #define ARGSIZE 9000 489 490 struct encap_parms { 491 u_int arglen; 492 char *args; 493 }; 494 495 static bool_t 496 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) 497 { 498 499 return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE)); 500 } 501 502 struct rmtcallargs { 503 u_long rmt_prog; 504 u_long rmt_vers; 505 u_long rmt_port; 506 u_long rmt_proc; 507 struct encap_parms rmt_args; 508 }; 509 510 static bool_t 511 xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 512 { 513 514 /* does not get a port number */ 515 if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 516 xdr_u_long(xdrs, &(cap->rmt_vers)) && 517 xdr_u_long(xdrs, &(cap->rmt_proc))) { 518 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 519 } 520 return (FALSE); 521 } 522 523 static bool_t 524 xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap) 525 { 526 if (xdr_u_long(xdrs, &(cap->rmt_port))) 527 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 528 return (FALSE); 529 } 530 531 /* 532 * only worries about the struct encap_parms part of struct rmtcallargs. 533 * The arglen must already be set!! 534 */ 535 static bool_t 536 xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 537 { 538 539 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 540 } 541 542 /* 543 * This routine finds and sets the length of incoming opaque paraters 544 * and then calls xdr_opaque_parms. 545 */ 546 static bool_t 547 xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 548 { 549 u_int beginpos, lowpos, highpos, currpos, pos; 550 551 beginpos = lowpos = pos = xdr_getpos(xdrs); 552 highpos = lowpos + ARGSIZE; 553 while (highpos >= lowpos) { 554 currpos = (lowpos + highpos) / 2; 555 if (xdr_setpos(xdrs, currpos)) { 556 pos = currpos; 557 lowpos = currpos + 1; 558 } else { 559 highpos = currpos - 1; 560 } 561 } 562 xdr_setpos(xdrs, beginpos); 563 cap->rmt_args.arglen = pos - beginpos; 564 return (xdr_opaque_parms(xdrs, cap)); 565 } 566 567 /* 568 * Call a remote procedure service 569 * This procedure is very quiet when things go wrong. 570 * The proc is written to support broadcast rpc. In the broadcast case, 571 * a machine should shut-up instead of complain, less the requestor be 572 * overrun with complaints at the expense of not hearing a valid reply ... 573 * 574 * This now forks so that the program & process that it calls can call 575 * back to the portmapper. 576 */ 577 void 578 callit(struct svc_req *rqstp, SVCXPRT *xprt) 579 { 580 struct rmtcallargs a; 581 struct pmaplist *pml; 582 u_short port; 583 struct sockaddr_in me; 584 pid_t pid; 585 int so = -1, dontblock = 1; 586 CLIENT *client; 587 struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; 588 struct timeval timeout; 589 char buf[ARGSIZE]; 590 591 timeout.tv_sec = 5; 592 timeout.tv_usec = 0; 593 a.rmt_args.args = buf; 594 if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a)) 595 return; 596 if (!check_callit(svc_getcaller(xprt), a.rmt_prog, a.rmt_proc)) 597 return; 598 if ((pml = find_service(a.rmt_prog, a.rmt_vers, 599 (u_long)IPPROTO_UDP)) == NULL) 600 return; 601 602 /* 603 * fork a child to do the work. Parent immediately returns. 604 * Child exits upon completion. 605 */ 606 if ((pid = fork()) != 0) { 607 if (pid == -1) 608 syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", 609 a.rmt_prog); 610 return; 611 } 612 port = pml->pml_map.pm_port; 613 get_myaddress(&me); 614 me.sin_port = htons(port); 615 616 /* Avoid implicit binding to reserved port by clntudp_create() */ 617 so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 618 if (so == -1) 619 exit(1); 620 if (ioctl(so, FIONBIO, &dontblock) == -1) 621 exit(1); 622 623 client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); 624 if (client != NULL) { 625 if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) 626 client->cl_auth = authunix_create(au->aup_machname, 627 au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); 628 a.rmt_port = (u_long)port; 629 if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, 630 xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) 631 svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); 632 AUTH_DESTROY(client->cl_auth); 633 clnt_destroy(client); 634 } 635 (void)close(so); 636 exit(0); 637 } 638 639 /* ARGSUSED */ 640 void 641 reap(int signo) 642 { 643 int save_errno = errno; 644 645 while (wait3(NULL, WNOHANG, NULL) > 0) 646 ; 647 errno = save_errno; 648 } 649 650 #define NFSPROG ((u_long) 100003) 651 #define MOUNTPROG ((u_long) 100005) 652 #define YPXPROG ((u_long) 100069) 653 #define YPPROG ((u_long) 100004) 654 #define YPPROC_DOMAIN_NONACK ((u_long) 2) 655 #define MOUNTPROC_MNT ((u_long) 1) 656 #define XXXPROC_NOP ((u_long) 0) 657 658 int 659 check_callit(struct sockaddr_in *addr, u_long prog, u_long aproc) 660 { 661 if ((prog == PMAPPROG && aproc != XXXPROC_NOP) || 662 (prog == NFSPROG && aproc != XXXPROC_NOP) || 663 (prog == YPXPROG && aproc != XXXPROC_NOP) || 664 (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || 665 (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { 666 syslog(LOG_WARNING, 667 "callit prog %ld aproc %ld (might be from %s)", 668 prog, aproc, inet_ntoa(addr->sin_addr)); 669 return (FALSE); 670 } 671 return (TRUE); 672 } 673