1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26 /* All Rights Reserved */ 27 /* 28 * University Copyright- Copyright (c) 1982, 1986, 1988 29 * The Regents of the University of California 30 * All Rights Reserved 31 * 32 * University Acknowledgment- Portions of this document are derived from 33 * software developed by the University of California, Berkeley, and its 34 * contributors. 35 */ 36 37 #pragma ident "%Z%%M% %I% %E% SMI" 38 /* 39 * rpcb_svc_com.c 40 * The commom server procedure for the rpcbind. 41 */ 42 43 #include <stdio.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <unistd.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <strings.h> 50 #include <rpc/rpc.h> 51 #include <rpc/rpcb_prot.h> 52 #include <netconfig.h> 53 #include <sys/param.h> 54 #include <errno.h> 55 #include <zone.h> 56 #include <sys/poll.h> 57 #include <sys/stropts.h> 58 #ifdef PORTMAP 59 #include <netinet/in.h> 60 #include <rpc/pmap_prot.h> 61 #endif /* PORTMAP */ 62 #include <syslog.h> 63 #include <netdir.h> 64 #include <ucred.h> 65 #include <alloca.h> 66 #include <rpcsvc/yp_prot.h> 67 #include <nfs/nfs.h> 68 #include <nfs/nfs_acl.h> 69 #include <rpcsvc/mount.h> 70 #include <nfs/nfs_acl.h> 71 #include <rpc/key_prot.h> 72 #include <rpcsvc/nfsauth_prot.h> 73 #include <rpcsvc/nispasswd.h> 74 #include <rpcsvc/yp_prot.h> 75 #include <rpcsvc/rquota.h> 76 #include <rpcsvc/yppasswd.h> 77 #include <rpcsvc/ypupd.h> 78 #include "rpcbind.h" 79 80 static bool_t xdr_opaque_parms(); 81 char *getowner(); 82 static ulong_t forward_register(); 83 static void handle_reply(); 84 static int netbufcmp(); 85 static int free_slot_by_xid(); 86 static int free_slot_by_index(); 87 static int check_rmtcalls(); 88 static void netbuffree(); 89 static void find_versions(); 90 static struct netbuf *netbufdup(); 91 static rpcblist_ptr find_service(); 92 static int add_pmaplist(RPCB *); 93 int del_pmaplist(RPCB *); 94 void delete_rbl(rpcblist_ptr); 95 96 static char *nullstring = ""; 97 static int rpcb_rmtcalls; 98 99 /* 100 * Set a mapping of program, version, netid 101 */ 102 /* ARGSUSED */ 103 bool_t * 104 rpcbproc_set_com(regp, rqstp, transp, rpcbversnum) 105 RPCB *regp; 106 struct svc_req *rqstp; /* Not used here */ 107 SVCXPRT *transp; 108 int rpcbversnum; 109 { 110 static bool_t ans; 111 char owner[64]; 112 113 #ifdef RPCBIND_DEBUG 114 fprintf(stderr, "RPCB_SET request for (%lu, %lu, %s, %s) : ", 115 regp->r_prog, regp->r_vers, regp->r_netid, regp->r_addr); 116 #endif 117 ans = map_set(regp, getowner(transp, owner)); 118 #ifdef RPCBIND_DEBUG 119 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 120 #endif 121 /* XXX: should have used some defined constant here */ 122 rpcbs_set((ulong_t)(rpcbversnum - 2), ans); 123 return (&ans); 124 } 125 126 bool_t 127 map_set(regp, owner) 128 RPCB *regp; 129 char *owner; 130 { 131 RPCB reg, *a; 132 rpcblist_ptr rbl, fnd; 133 134 reg = *regp; 135 /* 136 * check to see if already used 137 * find_service returns a hit even if 138 * the versions don't match, so check for it 139 */ 140 fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid); 141 if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) { 142 if (strcmp(fnd->rpcb_map.r_addr, reg.r_addr) == 0) 143 /* 144 * if these match then it is already 145 * registered so just say "OK". 146 */ 147 return (TRUE); 148 else { 149 /* 150 * Check if server is up. If so, return FALSE. 151 * If not, cleanup old registrations for the 152 * program and register the new server. 153 */ 154 if (is_bound(fnd->rpcb_map.r_netid, 155 fnd->rpcb_map.r_addr)) 156 return (FALSE); 157 delete_prog(reg.r_prog); 158 fnd = NULL; 159 } 160 } 161 /* 162 * add to the end of the list 163 */ 164 rbl = (rpcblist_ptr) malloc((uint_t)sizeof (RPCBLIST)); 165 if (rbl == (rpcblist_ptr)NULL) { 166 return (FALSE); 167 } 168 a = &(rbl->rpcb_map); 169 a->r_prog = reg.r_prog; 170 a->r_vers = reg.r_vers; 171 a->r_netid = strdup(reg.r_netid); 172 a->r_addr = strdup(reg.r_addr); 173 a->r_owner = strdup(owner); 174 if (a->r_addr == NULL || a->r_netid == NULL|| a->r_owner == NULL) { 175 delete_rbl(rbl); 176 return (FALSE); 177 } 178 rbl->rpcb_next = (rpcblist_ptr)NULL; 179 if (list_rbl == NULL) { 180 list_rbl = rbl; 181 } else { 182 for (fnd = list_rbl; fnd->rpcb_next; 183 fnd = fnd->rpcb_next) 184 ; 185 fnd->rpcb_next = rbl; 186 } 187 #ifdef PORTMAP 188 (void) add_pmaplist(regp); 189 #endif 190 return (TRUE); 191 } 192 193 /* 194 * Unset a mapping of program, version, netid 195 */ 196 /* ARGSUSED */ 197 bool_t * 198 rpcbproc_unset_com(regp, rqstp, transp, rpcbversnum) 199 RPCB *regp; 200 struct svc_req *rqstp; /* Not used here */ 201 SVCXPRT *transp; 202 int rpcbversnum; 203 { 204 static bool_t ans; 205 char owner[64]; 206 207 #ifdef RPCBIND_DEBUG 208 fprintf(stderr, "RPCB_UNSET request for (%lu, %lu, %s) : ", 209 regp->r_prog, regp->r_vers, regp->r_netid); 210 #endif 211 ans = map_unset(regp, getowner(transp, owner)); 212 #ifdef RPCBIND_DEBUG 213 fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 214 #endif 215 /* XXX: should have used some defined constant here */ 216 rpcbs_unset((ulong_t)(rpcbversnum - 2), ans); 217 return (&ans); 218 } 219 220 bool_t 221 map_unset(regp, owner) 222 RPCB *regp; 223 char *owner; 224 { 225 #ifdef PORTMAP 226 int ans = 0; 227 #endif 228 rpcblist_ptr rbl, next, prev = NULL; 229 230 if (owner == NULL) 231 return (0); 232 233 for (rbl = list_rbl; rbl != NULL; rbl = next) { 234 next = rbl->rpcb_next; 235 236 if ((rbl->rpcb_map.r_prog != regp->r_prog) || 237 (rbl->rpcb_map.r_vers != regp->r_vers) || 238 (regp->r_netid[0] && strcasecmp(regp->r_netid, 239 rbl->rpcb_map.r_netid))) { 240 /* prev moves forwards */ 241 prev = rbl; 242 continue; 243 } 244 /* 245 * Check whether appropriate uid. Unset only 246 * if superuser or the owner itself. 247 */ 248 if (strcmp(owner, "superuser") && 249 strcmp(rbl->rpcb_map.r_owner, owner)) 250 return (0); 251 /* prev stays */ 252 #ifdef PORTMAP 253 ans = 1; 254 #endif 255 delete_rbl(rbl); 256 257 if (prev == NULL) 258 list_rbl = next; 259 else 260 prev->rpcb_next = next; 261 } 262 #ifdef PORTMAP 263 if (ans) 264 (void) del_pmaplist(regp); 265 #endif 266 /* 267 * We return 1 either when the entry was not there or it 268 * was able to unset it. It can come to this point only if 269 * atleast one of the conditions is true. 270 */ 271 return (1); 272 } 273 274 void 275 delete_rbl(rpcblist_ptr rbl) 276 { 277 free(rbl->rpcb_map.r_addr); 278 free(rbl->rpcb_map.r_netid); 279 free(rbl->rpcb_map.r_owner); 280 free(rbl); 281 } 282 283 void 284 delete_prog(prog) 285 unsigned long prog; 286 { 287 rpcblist_ptr rbl, next, prev = NULL; 288 289 for (rbl = list_rbl; rbl != NULL; rbl = next) { 290 next = rbl->rpcb_next; 291 292 if (rbl->rpcb_map.r_prog != prog || 293 is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr)) { 294 prev = rbl; 295 continue; 296 } 297 298 #ifdef PORTMAP 299 (void) del_pmaplist(&rbl->rpcb_map); 300 #endif 301 delete_rbl(rbl); 302 303 if (prev == NULL) 304 list_rbl = next; 305 else 306 prev->rpcb_next = next; 307 } 308 } 309 310 /*ARGSUSED*/ 311 char ** 312 rpcbproc_getaddr_com(regp, rqstp, transp, rpcbversnum, verstype) 313 RPCB *regp; 314 struct svc_req *rqstp; /* Not used here */ 315 SVCXPRT *transp; 316 ulong_t rpcbversnum; 317 ulong_t verstype; 318 { 319 static char *uaddr; 320 char *saddr = NULL; 321 rpcblist_ptr fnd; 322 struct netconfig *trans_conf; /* transport netconfig */ 323 324 /* 325 * There is a potential window at startup during which rpcbind 326 * service has been established over IPv6 but not over IPv4. If an 327 * IPv4 request comes in during that window, the IP code will map 328 * it into IPv6. We could patch up the request so that it looks 329 * like IPv4 (so that rpcbind returns an IPv4 uaddr to the caller), 330 * but that requires some non-trivial code and it's hard to test. 331 * Instead, drop the request on the floor and force the caller to 332 * retransmit. By the time rpcbind sees the retransmission, IPv4 333 * service should be in place and it should see the request as 334 * IPv4, as desired. 335 */ 336 trans_conf = rpcbind_get_conf(transp->xp_netid); 337 if (strcmp(trans_conf->nc_protofmly, NC_INET6) == 0) { 338 struct sockaddr_in6 *rmtaddr; 339 340 rmtaddr = (struct sockaddr_in6 *)transp->xp_rtaddr.buf; 341 if (IN6_IS_ADDR_V4MAPPED(&rmtaddr->sin6_addr)) { 342 syslog(LOG_DEBUG, 343 "IPv4 GETADDR request mapped to IPv6: ignoring"); 344 return (NULL); 345 } 346 } 347 348 if (uaddr && uaddr[0]) 349 free((void *) uaddr); 350 fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid); 351 if (fnd && ((verstype == RPCB_ALLVERS) || 352 (regp->r_vers == fnd->rpcb_map.r_vers))) { 353 if (*(regp->r_addr) != '\0') { /* may contain a hint about */ 354 saddr = regp->r_addr; /* the interface that we */ 355 } /* should use */ 356 if (!(uaddr = mergeaddr(transp, transp->xp_netid, 357 fnd->rpcb_map.r_addr, saddr))) { 358 /* Try whatever we have */ 359 uaddr = strdup(fnd->rpcb_map.r_addr); 360 } else if (!uaddr[0]) { 361 /* 362 * The server died. Unset all versions of this prog. 363 */ 364 delete_prog(regp->r_prog); 365 uaddr = nullstring; 366 } 367 } else { 368 uaddr = nullstring; 369 } 370 #ifdef RPCBIND_DEBUG 371 fprintf(stderr, "getaddr: %s\n", uaddr); 372 #endif 373 /* XXX: should have used some defined constant here */ 374 rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers, 375 transp->xp_netid, uaddr); 376 return (&uaddr); 377 } 378 379 /* VARARGS */ 380 ulong_t * 381 rpcbproc_gettime_com() 382 { 383 static time_t curtime; 384 385 (void) time(&curtime); 386 return ((ulong_t *)&curtime); 387 } 388 389 /* 390 * Convert uaddr to taddr. Should be used only by 391 * local servers/clients. (kernel level stuff only) 392 */ 393 /* ARGSUSED */ 394 struct netbuf * 395 rpcbproc_uaddr2taddr_com(uaddrp, rqstp, transp, rpcbversnum) 396 char **uaddrp; 397 struct svc_req *rqstp; /* Not used here */ 398 SVCXPRT *transp; 399 int rpcbversnum; /* Not used here */ 400 { 401 struct netconfig *nconf; 402 static struct netbuf nbuf; 403 static struct netbuf *taddr; 404 405 if (taddr) { 406 free((void *) taddr->buf); 407 free((void *) taddr); 408 } 409 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) || 410 ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) { 411 (void) memset((char *)&nbuf, 0, sizeof (struct netbuf)); 412 return (&nbuf); 413 } 414 return (taddr); 415 } 416 417 /* 418 * Convert taddr to uaddr. Should be used only by 419 * local servers/clients. (kernel level stuff only) 420 */ 421 /* ARGSUSED */ 422 char ** 423 rpcbproc_taddr2uaddr_com(taddr, rqstp, transp, rpcbversnum) 424 struct netbuf *taddr; 425 struct svc_req *rqstp; /* Not used here */ 426 SVCXPRT *transp; 427 int rpcbversnum; /* unused */ 428 { 429 static char *uaddr; 430 struct netconfig *nconf; 431 432 #ifdef CHEW_FDS 433 int fd; 434 435 if ((fd = open("/dev/null", O_RDONLY)) == -1) { 436 uaddr = (char *)strerror(errno); 437 return (&uaddr); 438 } 439 #endif /* CHEW_FDS */ 440 if (uaddr && uaddr[0]) 441 free((void *) uaddr); 442 if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) || 443 ((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) { 444 uaddr = nullstring; 445 } 446 return (&uaddr); 447 } 448 449 450 /* 451 * Stuff for the rmtcall service 452 */ 453 struct encap_parms { 454 ulong_t arglen; 455 char *args; 456 }; 457 458 static bool_t 459 xdr_encap_parms(xdrs, epp) 460 XDR *xdrs; 461 struct encap_parms *epp; 462 { 463 return (xdr_bytes(xdrs, &(epp->args), (uint_t *)&(epp->arglen), ~0)); 464 } 465 466 467 struct r_rmtcall_args { 468 ulong_t rmt_prog; 469 ulong_t rmt_vers; 470 ulong_t rmt_proc; 471 int rmt_localvers; /* whether to send port # or uaddr */ 472 char *rmt_uaddr; 473 struct encap_parms rmt_args; 474 }; 475 476 /* 477 * XDR remote call arguments. It ignores the address part. 478 * written for XDR_DECODE direction only 479 */ 480 static bool_t 481 xdr_rmtcall_args(xdrs, cap) 482 register XDR *xdrs; 483 register struct r_rmtcall_args *cap; 484 { 485 /* does not get the address or the arguments */ 486 if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 487 xdr_u_long(xdrs, &(cap->rmt_vers)) && 488 xdr_u_long(xdrs, &(cap->rmt_proc))) { 489 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 490 } 491 return (FALSE); 492 } 493 494 /* 495 * XDR remote call results along with the address. Ignore 496 * program number, version number and proc number. 497 * Written for XDR_ENCODE direction only. 498 */ 499 static bool_t 500 xdr_rmtcall_result(xdrs, cap) 501 register XDR *xdrs; 502 register struct r_rmtcall_args *cap; 503 { 504 bool_t result; 505 506 #ifdef PORTMAP 507 if (cap->rmt_localvers == PMAPVERS) { 508 int h1, h2, h3, h4, p1, p2; 509 ulong_t port; 510 511 /* interpret the universal address for TCP/IP */ 512 if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d", 513 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 514 return (FALSE); 515 port = ((p1 & 0xff) << 8) + (p2 & 0xff); 516 result = xdr_u_long(xdrs, &port); 517 } else 518 #endif 519 if ((cap->rmt_localvers == RPCBVERS) || 520 (cap->rmt_localvers == RPCBVERS4)) { 521 result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr)); 522 } else { 523 return (FALSE); 524 } 525 if (result == TRUE) 526 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 527 return (FALSE); 528 } 529 530 /* 531 * only worries about the struct encap_parms part of struct r_rmtcall_args. 532 * The arglen must already be set!! 533 */ 534 static bool_t 535 xdr_opaque_parms(xdrs, cap) 536 XDR *xdrs; 537 struct r_rmtcall_args *cap; 538 { 539 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 540 } 541 542 struct rmtcallfd_list { 543 int fd; 544 SVCXPRT *xprt; 545 char *netid; 546 struct rmtcallfd_list *next; 547 }; 548 549 static struct rmtcallfd_list *rmthead; 550 static struct rmtcallfd_list *rmttail; 551 552 int 553 create_rmtcall_fd(nconf) 554 struct netconfig *nconf; 555 { 556 int fd; 557 struct rmtcallfd_list *rmt; 558 SVCXPRT *xprt; 559 560 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) { 561 if (debugging) 562 fprintf(stderr, 563 "create_rmtcall_fd: couldn't open \"%s\" (errno %d, t_errno %d)\n", 564 nconf->nc_device, errno, t_errno); 565 return (-1); 566 } 567 if (t_bind(fd, (struct t_bind *)0, 568 (struct t_bind *)0) == -1) { 569 if (debugging) 570 fprintf(stderr, 571 "create_rmtcall_fd: couldn't bind to fd for \"%s\" (errno %d, t_errno %d)\n", 572 nconf->nc_device, errno, t_errno); 573 return (-1); 574 } 575 xprt = svc_tli_create(fd, 0, (struct t_bind *)0, 0, 0); 576 if (xprt == NULL) { 577 if (debugging) 578 fprintf(stderr, 579 "create_rmtcall_fd: svc_tli_create failed\n"); 580 return (-1); 581 } 582 rmt = (struct rmtcallfd_list *)malloc((uint_t) 583 sizeof (struct rmtcallfd_list)); 584 if (rmt == NULL) { 585 syslog(LOG_ERR, "create_rmtcall_fd: no memory!"); 586 return (-1); 587 } 588 rmt->xprt = xprt; 589 rmt->netid = strdup(nconf->nc_netid); 590 xprt->xp_netid = rmt->netid; 591 rmt->fd = fd; 592 rmt->next = NULL; 593 if (rmthead == NULL) { 594 rmthead = rmt; 595 rmttail = rmt; 596 } else { 597 rmttail->next = rmt; 598 rmttail = rmt; 599 } 600 #if defined(DEBUG_RMTCALL) && defined(PORTMAP) 601 if (debugging) { 602 struct sockaddr_in *sin; 603 struct netbuf *nb; 604 nb = &xprt->xp_ltaddr; 605 sin = (struct sockaddr_in *)nb->buf; 606 fprintf(stderr, 607 "create_rmtcall_fd %d, port %d\n", 608 fd, sin->sin_port); 609 } 610 #endif 611 return (fd); 612 } 613 614 static int 615 find_rmtcallfd_by_netid(netid) 616 char *netid; 617 { 618 struct rmtcallfd_list *rmt; 619 620 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) { 621 if (strcmp(netid, rmt->netid) == 0) { 622 return (rmt->fd); 623 } 624 } 625 return (-1); 626 } 627 628 static SVCXPRT * 629 find_rmtcallxprt_by_fd(fd) 630 int fd; 631 { 632 struct rmtcallfd_list *rmt; 633 634 for (rmt = rmthead; rmt != NULL; rmt = rmt->next) { 635 if (fd == rmt->fd) { 636 return (rmt->xprt); 637 } 638 } 639 return (NULL); 640 } 641 642 643 /* 644 * Call a remote procedure service. This procedure is very quiet when things 645 * go wrong. The proc is written to support broadcast rpc. In the broadcast 646 * case, a machine should shut-up instead of complain, lest the requestor be 647 * overrun with complaints at the expense of not hearing a valid reply. 648 * When receiving a request and verifying that the service exists, we 649 * 650 * receive the request 651 * 652 * open a new TLI endpoint on the same transport on which we received 653 * the original request 654 * 655 * remember the original request's XID (which requires knowing the format 656 * of the svc_dg_data structure) 657 * 658 * forward the request, with a new XID, to the requested service, 659 * remembering the XID used to send this request (for later use in 660 * reassociating the answer with the original request), the requestor's 661 * address, the file descriptor on which the forwarded request is 662 * made and the service's address. 663 * 664 * mark the file descriptor on which we anticipate receiving a reply from 665 * the service and one to select for in our private svc_run procedure 666 * 667 * At some time in the future, a reply will be received from the service to 668 * which we forwarded the request. At that time, we detect that the socket 669 * used was for forwarding (by looking through the finfo structures to see 670 * whether the fd corresponds to one of those) and call handle_reply() to 671 * 672 * receive the reply 673 * 674 * bundle the reply, along with the service's universal address 675 * 676 * create a SVCXPRT structure and use a version of svc_sendreply 677 * that allows us to specify the reply XID and destination, send the reply 678 * to the original requestor. 679 */ 680 681 /* begin kludge XXX */ 682 /* 683 * This is from .../libnsl/rpc/svc_dg.c, and is the structure that xprt->xp_p2 684 * points to (and shouldn't be here - we should know nothing of its structure). 685 */ 686 #define MAX_OPT_WORDS 128 687 #define RPC_BUF_MAX 65536 /* can be raised if required */ 688 struct svc_dg_data { 689 /* XXX: optbuf should be the first field, used by ti_opts.c code */ 690 struct netbuf optbuf; /* netbuf for options */ 691 long opts[MAX_OPT_WORDS]; /* options */ 692 uint_t su_iosz; /* size of send.recv buffer */ 693 ulong_t su_xid; /* transaction id */ 694 XDR su_xdrs; /* XDR handle */ 695 char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ 696 char *su_cache; /* cached data, NULL if none */ 697 struct t_unitdata su_tudata; /* tu_data for recv */ 698 }; 699 #define getbogus_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2)) 700 701 /* 702 * This is from ../ypcmd/yp_b.h 703 * It does not appear in <rpcsvc/yp_prot.h> 704 */ 705 #define YPBINDPROG ((ulong_t)100007) 706 #define YPBINDPROC_SETDOM ((ulong_t)2) 707 708 /* end kludge XXX */ 709 710 void 711 rpcbproc_callit_com(rqstp, transp, reply_type, versnum) 712 struct svc_req *rqstp; 713 SVCXPRT *transp; 714 ulong_t reply_type; /* which proc number */ 715 ulong_t versnum; /* which vers was called */ 716 { 717 register rpcblist_ptr rbl; 718 struct netconfig *nconf; 719 struct netbuf *caller; 720 struct r_rmtcall_args a; 721 char *buf_alloc = NULL; 722 char *outbuf_alloc = NULL; 723 char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX]; 724 struct netbuf *na = (struct netbuf *)NULL; 725 struct t_info tinfo; 726 struct t_unitdata tu_data; 727 struct rpc_msg call_msg; 728 struct svc_dg_data *bd; 729 int outlen; 730 uint_t sendsz; 731 XDR outxdr; 732 AUTH *auth; 733 int fd = -1; 734 char *uaddr; 735 struct nd_mergearg ma; 736 int stat; 737 738 if (t_getinfo(transp->xp_fd, &tinfo) == -1) { 739 if (reply_type == RPCBPROC_INDIRECT) 740 svcerr_systemerr(transp); 741 return; 742 } 743 if (tinfo.servtype != T_CLTS) 744 return; /* Only datagram type accepted */ 745 sendsz = __rpc_get_t_size(0, tinfo.tsdu); 746 if (sendsz == 0) { /* data transfer not supported */ 747 if (reply_type == RPCBPROC_INDIRECT) 748 svcerr_systemerr(transp); 749 return; 750 } 751 /* 752 * Should be multiple of 4 for XDR. 753 */ 754 sendsz = ((sendsz + 3) / 4) * 4; 755 if (sendsz > RPC_BUF_MAX) { 756 #ifdef notyet 757 buf_alloc = alloca(sendsz); /* not in IDR2? */ 758 #else 759 buf_alloc = malloc(sendsz); 760 #endif /* notyet */ 761 if (buf_alloc == NULL) { 762 if (debugging) 763 fprintf(stderr, 764 "rpcbproc_callit_com: No Memory!\n"); 765 if (reply_type == RPCBPROC_INDIRECT) 766 svcerr_systemerr(transp); 767 return; 768 } 769 a.rmt_args.args = buf_alloc; 770 } else { 771 a.rmt_args.args = buf; 772 } 773 774 call_msg.rm_xid = 0; /* For error checking purposes */ 775 ma.m_uaddr = NULL; 776 if (!svc_getargs(transp, (xdrproc_t)xdr_rmtcall_args, (char *)&a)) { 777 if (reply_type == RPCBPROC_INDIRECT) 778 svcerr_decode(transp); 779 if (debugging) 780 fprintf(stderr, 781 "rpcbproc_callit_com: svc_getargs failed\n"); 782 goto error; 783 } 784 if (!allow_indirect) 785 goto error; 786 caller = svc_getrpccaller(transp); 787 #ifdef RPCBIND_DEBUG 788 uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller); 789 fprintf(stderr, "%s %s request for (%lu, %lu, %lu, %s) from %s : ", 790 versnum == PMAPVERS ? "pmap_rmtcall" : 791 versnum == RPCBVERS ? "rpcb_rmtcall" : 792 versnum == RPCBVERS4 ? "rpcb_indirect" : "unknown", 793 reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit", 794 a.rmt_prog, a.rmt_vers, a.rmt_proc, transp->xp_netid, 795 uaddr ? uaddr : "unknown"); 796 if (uaddr) 797 free((void *) uaddr); 798 #endif 799 800 /* 801 * Disallow calling rpcbind for certain procedures. 802 * Allow calling NULLPROC - per man page on rpcb_rmtcall(). 803 * switch is in alphabetical order. 804 */ 805 if (a.rmt_proc != NULLPROC) { 806 switch (a.rmt_prog) { 807 case KEY_PROG: 808 if (debugging) 809 fprintf(stderr, 810 "rpcbind: rejecting KEY_PROG(%d)\n", 811 a.rmt_proc); 812 goto error; 813 case MOUNTPROG: 814 if (a.rmt_proc != MOUNTPROC_MNT) 815 break; 816 /* 817 * In Solaris 2.6, the host-based accesss control 818 * is done by the NFS server on each request. 819 * Prior to 2.6 we rely on mountd. 820 */ 821 if (debugging) 822 fprintf(stderr, 823 "rpcbind: rejecting MOUNTPROG(%d)\n", 824 a.rmt_proc); 825 goto error; 826 case NFSAUTH_PROG: 827 if (debugging) 828 fprintf(stderr, 829 "rpcbind: rejecting NFSAUTH_PROG(%d)\n", 830 a.rmt_proc); 831 goto error; 832 case NFS_ACL_PROGRAM: 833 if (debugging) 834 fprintf(stderr, 835 "rpcbind: rejecting NFS_ACL_PROGRAM(%d)\n", 836 a.rmt_proc); 837 goto error; 838 case NFS_PROGRAM: 839 /* also NFS3_PROGRAM */ 840 if (debugging) 841 fprintf(stderr, 842 "rpcbind: rejecting NFS_PROGRAM(%d)\n", 843 a.rmt_proc); 844 goto error; 845 case RPCBPROG: 846 /* 847 * Disallow calling rpcbind for certain procedures. 848 * Luckily Portmap set/unset/callit also have same 849 * procedure numbers. So, will not check for those. 850 */ 851 switch (a.rmt_proc) { 852 case RPCBPROC_SET: 853 case RPCBPROC_UNSET: 854 case RPCBPROC_CALLIT: 855 case RPCBPROC_INDIRECT: 856 if (reply_type == RPCBPROC_INDIRECT) 857 svcerr_weakauth(transp); /* XXX */ 858 if (debugging) 859 fprintf(stderr, 860 "rpcbproc_callit_com: calling RPCBPROG procs SET, UNSET, CALLIT, or INDIRECT \ 861 not allowed \n"); 862 goto error; 863 default: 864 /* 865 * Ideally, we should have called rpcb_service() 866 * or pmap_service() with appropriate parameters 867 * instead of going about in a roundabout 868 * manner. Hopefully, this case should happen 869 * rarely. 870 */ 871 break; 872 } 873 break; 874 case RQUOTAPROG: 875 if (debugging) 876 fprintf(stderr, 877 "rpcbind: rejecting RQUOTAPROG(%d)\n", 878 a.rmt_proc); 879 goto error; 880 case YPPASSWDPROG: 881 if (debugging) 882 fprintf(stderr, 883 "rpcbind: rejecting YPPASSWDPROG(%d)\n", 884 a.rmt_proc); 885 goto error; 886 case YPU_PROG: 887 if (debugging) 888 fprintf(stderr, 889 "rpcbind: rejecting YPU_PROG(%d)\n", 890 a.rmt_proc); 891 goto error; 892 case YPBINDPROG: 893 if (a.rmt_proc != YPBINDPROC_SETDOM) 894 break; 895 if (debugging) 896 fprintf(stderr, 897 "rpcbind: rejecting YPBINDPROG(%d)\n", 898 a.rmt_proc); 899 goto error; 900 case YPPROG: 901 switch (a.rmt_proc) { 902 case YPPROC_FIRST: 903 case YPPROC_NEXT: 904 case YPPROC_MATCH: 905 case YPPROC_ALL: 906 if (debugging) 907 fprintf(stderr, 908 "rpcbind: rejecting YPPROG(%d)\n", 909 a.rmt_proc); 910 goto error; 911 default: 912 break; 913 } 914 break; 915 default: 916 break; 917 } 918 } 919 920 rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid); 921 922 rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers, 923 a.rmt_proc, transp->xp_netid, rbl); 924 925 if (rbl == (rpcblist_ptr)NULL) { 926 #ifdef RPCBIND_DEBUG 927 fprintf(stderr, "not found\n"); 928 #endif 929 if (reply_type == RPCBPROC_INDIRECT) 930 svcerr_noprog(transp); 931 goto error; 932 } 933 if (rbl->rpcb_map.r_vers != a.rmt_vers) { 934 #ifdef RPCBIND_DEBUG 935 fprintf(stderr, "version not found\n"); 936 #endif 937 if (reply_type == RPCBPROC_INDIRECT) { 938 ulong_t vers_low, vers_high; 939 940 find_versions(a.rmt_prog, transp->xp_netid, 941 &vers_low, &vers_high); 942 svcerr_progvers(transp, vers_low, vers_high); 943 } 944 goto error; 945 } 946 947 #ifdef RPCBIND_DEBUG 948 fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr); 949 #endif 950 /* 951 * Check whether this entry is valid and a server is present 952 * Mergeaddr() returns NULL if no such entry is present, and 953 * returns "" if the entry was present but the server is not 954 * present (i.e., it crashed). 955 */ 956 if (reply_type == RPCBPROC_INDIRECT) { 957 uaddr = mergeaddr(transp, transp->xp_netid, 958 rbl->rpcb_map.r_addr, NULL); 959 if ((uaddr == (char *)NULL) || uaddr[0] == '\0') { 960 svcerr_noprog(transp); 961 goto error; 962 } else { 963 free((void *) uaddr); 964 } 965 } 966 nconf = rpcbind_get_conf(transp->xp_netid); 967 if (nconf == (struct netconfig *)NULL) { 968 if (reply_type == RPCBPROC_INDIRECT) 969 svcerr_systemerr(transp); 970 if (debugging) 971 fprintf(stderr, 972 "rpcbproc_callit_com: rpcbind_get_conf failed\n"); 973 goto error; 974 } 975 ma.c_uaddr = taddr2uaddr(nconf, caller); 976 ma.s_uaddr = rbl->rpcb_map.r_addr; 977 /* 978 * A mergeaddr operation allocates a string, which it stores in 979 * ma.m_uaddr. It's passed to forward_register() and is 980 * eventually freed by free_slot_*(). 981 */ 982 983 stat = netdir_options(nconf, ND_MERGEADDR, 0, (char *)&ma); 984 free((void *) ma.c_uaddr); 985 if (stat) 986 (void) syslog(LOG_ERR, "netdir_merge failed for %s: %s", 987 nconf->nc_netid, netdir_sperror()); 988 #ifdef ND_DEBUG 989 fprintf(stderr, 990 "rpcbproc_callit_com: s_uaddr = %s, c_uaddr = %s, merged m_uaddr = %s\n", 991 ma.s_uaddr, ma.c_uaddr, ma.m_uaddr); 992 #endif 993 if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) { 994 if (reply_type == RPCBPROC_INDIRECT) 995 svcerr_systemerr(transp); 996 free((void *) ma.m_uaddr); 997 ma.m_uaddr = NULL; 998 goto error; 999 } 1000 bd = getbogus_data(transp); 1001 call_msg.rm_xid = forward_register(bd->su_xid, 1002 caller, fd, ma.m_uaddr, reply_type, versnum); 1003 if (call_msg.rm_xid == 0) { 1004 /* 1005 * A duplicate request for the slow server. Let's not 1006 * beat on it any more. 1007 */ 1008 if (debugging) 1009 fprintf(stderr, 1010 "rpcbproc_callit_com: duplicate request\n"); 1011 free((void *) ma.m_uaddr); 1012 ma.m_uaddr = NULL; 1013 goto error; 1014 } else if (call_msg.rm_xid == (uint32_t)-1) { 1015 /* forward_register failed. Perhaps no memory. */ 1016 if (debugging) 1017 fprintf(stderr, 1018 "rpcbproc_callit_com: forward_register failed\n"); 1019 free((void *) ma.m_uaddr); 1020 ma.m_uaddr = NULL; 1021 goto error; 1022 } 1023 1024 #ifdef DEBUG_RMTCALL 1025 fprintf(stderr, 1026 "rpcbproc_callit_com: original XID %x, new XID %x\n", 1027 bd->su_xid, call_msg.rm_xid); 1028 #endif 1029 call_msg.rm_direction = CALL; 1030 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 1031 call_msg.rm_call.cb_prog = a.rmt_prog; 1032 call_msg.rm_call.cb_vers = a.rmt_vers; 1033 if (sendsz > RPC_BUF_MAX) { 1034 #ifdef notyet 1035 outbuf_alloc = alloca(sendsz); /* not in IDR2? */ 1036 #else 1037 outbuf_alloc = malloc(sendsz); 1038 #endif /* notyet */ 1039 if (outbuf_alloc == NULL) { 1040 if (reply_type == RPCBPROC_INDIRECT) 1041 svcerr_systemerr(transp); 1042 if (debugging) 1043 fprintf(stderr, 1044 "rpcbproc_callit_com: No memory!\n"); 1045 goto error; 1046 } 1047 xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE); 1048 } else { 1049 xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE); 1050 } 1051 if (!xdr_callhdr(&outxdr, &call_msg)) { 1052 if (reply_type == RPCBPROC_INDIRECT) 1053 svcerr_systemerr(transp); 1054 if (debugging) 1055 fprintf(stderr, 1056 "rpcbproc_callit_com: xdr_callhdr failed\n"); 1057 goto error; 1058 } 1059 if (!xdr_u_long(&outxdr, &(a.rmt_proc))) { 1060 if (reply_type == RPCBPROC_INDIRECT) 1061 svcerr_systemerr(transp); 1062 if (debugging) 1063 fprintf(stderr, 1064 "rpcbproc_callit_com: xdr_u_long failed\n"); 1065 goto error; 1066 } 1067 1068 if (rqstp->rq_cred.oa_flavor == AUTH_NULL) { 1069 auth = authnone_create(); 1070 } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) { 1071 struct authsys_parms *au; 1072 1073 au = (struct authsys_parms *)rqstp->rq_clntcred; 1074 auth = authsys_create(au->aup_machname, 1075 au->aup_uid, au->aup_gid, 1076 au->aup_len, au->aup_gids); 1077 if (auth == NULL) /* fall back */ 1078 auth = authnone_create(); 1079 } else { 1080 /* we do not support any other authentication scheme */ 1081 if (debugging) 1082 fprintf(stderr, 1083 "rpcbproc_callit_com: oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n"); 1084 if (reply_type == RPCBPROC_INDIRECT) 1085 svcerr_weakauth(transp); /* XXX too strong.. */ 1086 goto error; 1087 } 1088 if (auth == NULL) { 1089 if (reply_type == RPCBPROC_INDIRECT) 1090 svcerr_systemerr(transp); 1091 if (debugging) 1092 fprintf(stderr, 1093 "rpcbproc_callit_com: authwhatever_create returned NULL\n"); 1094 goto error; 1095 } 1096 if (!AUTH_MARSHALL(auth, &outxdr)) { 1097 if (reply_type == RPCBPROC_INDIRECT) 1098 svcerr_systemerr(transp); 1099 AUTH_DESTROY(auth); 1100 if (debugging) 1101 fprintf(stderr, 1102 "rpcbproc_callit_com: AUTH_MARSHALL failed\n"); 1103 goto error; 1104 } 1105 AUTH_DESTROY(auth); 1106 if (!xdr_opaque_parms(&outxdr, &a)) { 1107 if (reply_type == RPCBPROC_INDIRECT) 1108 svcerr_systemerr(transp); 1109 if (debugging) 1110 fprintf(stderr, 1111 "rpcbproc_callit_com: xdr_opaque_parms failed\n"); 1112 goto error; 1113 } 1114 outlen = (int)XDR_GETPOS(&outxdr); 1115 if (outbuf_alloc) 1116 tu_data.udata.buf = outbuf_alloc; 1117 else 1118 tu_data.udata.buf = outbuf; 1119 tu_data.udata.len = outlen; 1120 tu_data.opt.len = 0; 1121 1122 na = uaddr2taddr(nconf, ma.m_uaddr); 1123 if (!na) { 1124 if (reply_type == RPCBPROC_INDIRECT) 1125 svcerr_systemerr(transp); 1126 goto error; 1127 } 1128 tu_data.addr = *na; 1129 1130 if (t_sndudata(fd, &tu_data) == -1) { 1131 if (debugging) 1132 fprintf(stderr, 1133 "rpcbproc_callit_com: t_sndudata failed: t_errno %d, errno %d\n", 1134 t_errno, errno); 1135 if (reply_type == RPCBPROC_INDIRECT) 1136 svcerr_systemerr(transp); 1137 goto error; 1138 } 1139 goto out; 1140 1141 error: 1142 if ((call_msg.rm_xid != 0) && (ma.m_uaddr != NULL)) 1143 (void) free_slot_by_xid(call_msg.rm_xid, ma.m_uaddr); 1144 out: 1145 if (buf_alloc) 1146 free((void *) buf_alloc); 1147 if (outbuf_alloc) 1148 free((void *) outbuf_alloc); 1149 if (na) 1150 netdir_free((char *)na, ND_ADDR); 1151 } 1152 1153 #define NFORWARD 64 1154 #define MAXTIME_OFF 300 /* 5 minutes */ 1155 1156 struct finfo { 1157 int flag; 1158 #define FINFO_ACTIVE 0x1 1159 ulong_t caller_xid; 1160 struct netbuf *caller_addr; 1161 ulong_t forward_xid; 1162 int forward_fd; 1163 char *uaddr; 1164 ulong_t reply_type; 1165 ulong_t versnum; 1166 time_t time; 1167 }; 1168 static struct finfo FINFO[NFORWARD]; 1169 /* 1170 * Makes an entry into the FIFO for the given request. 1171 * If duplicate request, returns a 0, else returns the xid of its call. 1172 */ 1173 static ulong_t 1174 forward_register(caller_xid, caller_addr, forward_fd, uaddr, 1175 reply_type, versnum) 1176 ulong_t caller_xid; 1177 struct netbuf *caller_addr; 1178 int forward_fd; 1179 char *uaddr; 1180 ulong_t reply_type; 1181 ulong_t versnum; 1182 { 1183 int i; 1184 int j = 0; 1185 time_t min_time, time_now; 1186 static ulong_t lastxid; 1187 int entry = -1; 1188 1189 min_time = FINFO[0].time; 1190 time_now = time((time_t *)0); 1191 /* 1192 * initialization: once this has happened, lastxid will 1193 * - always be a multiple of NFORWARD (which has to be a power of 2), 1194 * - never be 0 again, 1195 * - never be (ulong_t)(-NFORWARD) 1196 * when entering or returning from this function. 1197 */ 1198 if (lastxid == 0) { 1199 lastxid = time_now * NFORWARD; 1200 /* 1201 * avoid lastxid wraparound to 0, 1202 * and generating a forward_xid of -1 1203 */ 1204 if (lastxid >= (ulong_t)(-NFORWARD)) 1205 lastxid = NFORWARD; 1206 } 1207 1208 /* 1209 * Check if it is an duplicate entry. Then, 1210 * try to find an empty slot. If not available, then 1211 * use the slot with the earliest time. 1212 */ 1213 for (i = 0; i < NFORWARD; i++) { 1214 if (FINFO[i].flag & FINFO_ACTIVE) { 1215 if ((FINFO[i].caller_xid == caller_xid) && 1216 (FINFO[i].reply_type == reply_type) && 1217 (FINFO[i].versnum == versnum) && 1218 (!netbufcmp(FINFO[i].caller_addr, 1219 caller_addr))) { 1220 FINFO[i].time = time((time_t *)0); 1221 return (0); /* Duplicate entry */ 1222 } else { 1223 /* Should we wait any longer */ 1224 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 1225 (void) free_slot_by_index(i); 1226 } 1227 } 1228 if (entry == -1) { 1229 if ((FINFO[i].flag & FINFO_ACTIVE) == 0) { 1230 entry = i; 1231 } else if (FINFO[i].time < min_time) { 1232 j = i; 1233 min_time = FINFO[i].time; 1234 } 1235 } 1236 } 1237 if (entry != -1) { 1238 /* use this empty slot */ 1239 j = entry; 1240 } else { 1241 (void) free_slot_by_index(j); 1242 } 1243 if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) { 1244 return ((ulong_t)-1); 1245 } 1246 rpcb_rmtcalls++; /* no of pending calls */ 1247 FINFO[j].flag = FINFO_ACTIVE; 1248 FINFO[j].reply_type = reply_type; 1249 FINFO[j].versnum = versnum; 1250 FINFO[j].time = time_now; 1251 FINFO[j].caller_xid = caller_xid; 1252 FINFO[j].forward_fd = forward_fd; 1253 /* 1254 * Though uaddr is not allocated here, it will still be freed 1255 * from free_slot_*(). 1256 */ 1257 FINFO[j].uaddr = uaddr; 1258 lastxid = lastxid + NFORWARD; 1259 /* avoid lastxid wraparound to 0, and generating a forward_xid of -1 */ 1260 if (lastxid >= (ulong_t)(-NFORWARD)) 1261 lastxid = NFORWARD; 1262 1263 FINFO[j].forward_xid = lastxid + j; /* encode slot */ 1264 return (FINFO[j].forward_xid); /* forward on this xid */ 1265 } 1266 1267 static struct finfo * 1268 forward_find(reply_xid, uaddr) 1269 ulong_t reply_xid; 1270 char *uaddr; 1271 { 1272 int i; 1273 1274 i = reply_xid % NFORWARD; 1275 if (i < 0) 1276 i += NFORWARD; 1277 if ((FINFO[i].flag & FINFO_ACTIVE) && 1278 (strcmp(FINFO[i].uaddr, uaddr) == 0) && 1279 (FINFO[i].forward_xid == reply_xid)) { 1280 return (&FINFO[i]); 1281 } 1282 return (NULL); 1283 } 1284 1285 static int 1286 free_slot_by_xid(xid, uaddr) 1287 ulong_t xid; 1288 char *uaddr; 1289 { 1290 int entry; 1291 1292 if (forward_find(xid, uaddr)) { 1293 entry = xid % NFORWARD; 1294 if (entry < 0) 1295 entry += NFORWARD; 1296 return (free_slot_by_index(entry)); 1297 } 1298 return (0); 1299 } 1300 1301 static int 1302 free_slot_by_index(index) 1303 int index; 1304 { 1305 struct finfo *fi; 1306 1307 fi = &FINFO[index]; 1308 if (fi->flag & FINFO_ACTIVE) { 1309 netbuffree(fi->caller_addr); 1310 free((void *) fi->uaddr); 1311 fi->flag &= ~FINFO_ACTIVE; 1312 rpcb_rmtcalls--; 1313 return (1); 1314 } 1315 return (0); 1316 } 1317 1318 static int 1319 netbufcmp(n1, n2) 1320 struct netbuf *n1, *n2; 1321 { 1322 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); 1323 } 1324 1325 static struct netbuf * 1326 netbufdup(ap) 1327 register struct netbuf *ap; 1328 { 1329 register struct netbuf *np; 1330 1331 np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len); 1332 if (np) { 1333 np->maxlen = np->len = ap->len; 1334 np->buf = ((char *)np) + sizeof (struct netbuf); 1335 (void) memcpy(np->buf, ap->buf, ap->len); 1336 } 1337 return (np); 1338 } 1339 1340 static void 1341 netbuffree(ap) 1342 register struct netbuf *ap; 1343 { 1344 free((void *) ap); 1345 } 1346 1347 /* 1348 * active_fd is used to determine whether an entry in svc_pollfd is: 1349 * 1. not a forward fd (should be polled) 1350 * 2. an active forward fd (should be polled) 1351 * 3. an inactive forward fd (should not be polled) 1352 */ 1353 static bool_t 1354 active_fd(fd) 1355 int fd; 1356 { 1357 int i; 1358 time_t time_now; 1359 1360 if (find_rmtcallxprt_by_fd(fd) == (SVCXPRT *)NULL) 1361 return (TRUE); 1362 if (rpcb_rmtcalls == 0) 1363 return (FALSE); 1364 time_now = time((time_t *)0); 1365 for (i = 0; i < NFORWARD; i++) 1366 if (FINFO[i].forward_fd == fd) { 1367 if (FINFO[i].flag & FINFO_ACTIVE) { 1368 /* Should we wait any longer */ 1369 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 1370 (void) free_slot_by_index(i); 1371 else 1372 return (TRUE); 1373 } 1374 } 1375 return (FALSE); 1376 } 1377 1378 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) 1379 1380 void 1381 my_svc_run() 1382 { 1383 size_t nfds; 1384 struct pollfd pollfds[FD_SETSIZE]; 1385 int poll_ret, check_ret; 1386 #ifdef SVC_RUN_DEBUG 1387 int i; 1388 #endif 1389 register struct pollfd *p; 1390 1391 for (;;) { 1392 { 1393 register pollfd_t *in; 1394 register int n; /* loop counter */ 1395 1396 /* 1397 * compress the sparse svc_pollfd strcutre 1398 * into pollfds 1399 */ 1400 memset(pollfds, 0, sizeof (pollfds)); 1401 p = pollfds; 1402 for (in = svc_pollfd, n = 0; n < svc_max_pollfd; 1403 n++, in++) { 1404 if ((in->fd >= 0) && active_fd(in->fd)) { 1405 p->fd = in->fd; 1406 p->events = MASKVAL; 1407 p->revents = 0; 1408 p++; 1409 } 1410 } 1411 nfds = p - pollfds; 1412 } 1413 poll_ret = 0; 1414 #ifdef SVC_RUN_DEBUG 1415 if (debugging) { 1416 fprintf(stderr, "polling for read on fd < "); 1417 for (i = 0, p = pollfds; i < nfds; i++, p++) 1418 if (p->events) 1419 fprintf(stderr, "%d ", p->fd); 1420 fprintf(stderr, ">\n"); 1421 } 1422 #endif 1423 switch (poll_ret = poll(pollfds, nfds, INFTIM)) { 1424 case -1: 1425 /* 1426 * We ignore all errors, continuing with the assumption 1427 * that it was set by the signal handlers (or any 1428 * other outside event) and not caused by poll(). 1429 * If it was our refresh signal, call the refresh 1430 * function. 1431 */ 1432 if (sigrefresh) { 1433 sigrefresh = 0; 1434 rpcb_check_init(); 1435 } 1436 case 0: 1437 continue; 1438 default: 1439 #ifdef SVC_RUN_DEBUG 1440 if (debugging) { 1441 fprintf(stderr, "poll returned read fds < "); 1442 for (i = 0, p = pollfds; i < nfds; i++, p++) 1443 if (p->revents) 1444 fprintf(stderr, "%d ", p->fd); 1445 fprintf(stderr, ">\n"); 1446 } 1447 #endif 1448 /* 1449 * If we found as many replies on callback fds 1450 * as the number of descriptors selectable which 1451 * poll() returned, there can be no more so we 1452 * don't call svc_getreq_poll. Otherwise, there 1453 * must be another so we must call svc_getreq_poll. 1454 */ 1455 if ((check_ret = check_rmtcalls(pollfds, nfds)) == 1456 poll_ret) 1457 continue; 1458 svc_getreq_poll(pollfds, poll_ret-check_ret); 1459 } 1460 } 1461 } 1462 1463 static int 1464 check_rmtcalls(pfds, nfds) 1465 struct pollfd *pfds; 1466 int nfds; 1467 { 1468 int j, ncallbacks_found = 0; 1469 SVCXPRT *xprt; 1470 1471 /* 1472 * This fd will not be polled if rpcb_rmtcalls == 0 1473 */ 1474 if (rpcb_rmtcalls == 0) 1475 return (0); 1476 1477 for (j = 0; j < nfds; j++) { 1478 if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) { 1479 if (pfds[j].revents) { 1480 ncallbacks_found++; 1481 #ifdef DEBUG_RMTCALL 1482 if (debugging) 1483 fprintf(stderr, 1484 "my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n", 1485 pfds[j].fd, xprt->xp_netid); 1486 #endif 1487 handle_reply(pfds[j].fd, xprt); 1488 pfds[j].revents = 0; 1489 } 1490 } 1491 } 1492 return (ncallbacks_found); 1493 } 1494 1495 static void 1496 xprt_set_caller(xprt, fi) 1497 SVCXPRT *xprt; 1498 struct finfo *fi; 1499 { 1500 struct svc_dg_data *bd; 1501 1502 *(svc_getrpccaller(xprt)) = *(fi->caller_addr); 1503 bd = (struct svc_dg_data *)getbogus_data(xprt); 1504 bd->su_xid = fi->caller_xid; /* set xid on reply */ 1505 } 1506 1507 /* 1508 * Call svcerr_systemerr() only if RPCBVERS4 1509 */ 1510 static void 1511 send_svcsyserr(xprt, fi) 1512 SVCXPRT *xprt; 1513 struct finfo *fi; 1514 { 1515 if (fi->reply_type == RPCBPROC_INDIRECT) { 1516 xprt_set_caller(xprt, fi); 1517 svcerr_systemerr(xprt); 1518 } 1519 } 1520 1521 static void 1522 handle_reply(fd, xprt) 1523 int fd; 1524 SVCXPRT *xprt; 1525 { 1526 XDR reply_xdrs; 1527 struct rpc_msg reply_msg; 1528 struct rpc_err reply_error; 1529 char *buffer; 1530 struct finfo *fi = NULL; 1531 int inlen, pos, len, res, i; 1532 struct r_rmtcall_args a; 1533 struct t_unitdata *tr_data = NULL, *tu_data; 1534 struct netconfig *nconf = NULL; 1535 char *uaddr = NULL; 1536 1537 nconf = rpcbind_get_conf(xprt->xp_netid); 1538 if (nconf == NULL) { 1539 #ifdef SVC_RUN_DEBUG 1540 if (debugging) 1541 fprintf(stderr, "handle_reply: null xp_netid\n"); 1542 #endif 1543 goto done; 1544 } 1545 /* 1546 * If this fd is not active on the forward list, ignore it 1547 * If the svc_pollfd structure has multiple settings 1548 * of the same fd, then it will enter handle_reply() for the first one, 1549 * set FINFO_ACTIVE false and then get another call to handle_reply() 1550 * with the same, now inactive, fd. 1551 */ 1552 1553 for (i = 0; i < NFORWARD; i++) { 1554 if ((FINFO[i].forward_fd == fd) && 1555 (FINFO[i].flag & FINFO_ACTIVE)) 1556 break; 1557 } 1558 1559 if (i == NFORWARD) { 1560 #ifdef SVC_RUN_DEBUG 1561 if (debugging) { 1562 fprintf(stderr, "Unsolicited message on rmtcall fd\n"); 1563 } 1564 #endif 1565 return; 1566 } 1567 1568 reply_msg.rm_xid = 0; /* for easier error handling */ 1569 tr_data = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, 1570 T_ADDR | T_UDATA); 1571 if (tr_data == (struct t_unitdata *)NULL) { 1572 if (debugging) 1573 fprintf(stderr, 1574 "handle_reply: t_alloc T_UNITDATA failed\n"); 1575 goto done; 1576 } 1577 do { 1578 int moreflag; 1579 1580 moreflag = 0; 1581 if (errno == EINTR) 1582 errno = 0; 1583 res = t_rcvudata(fd, tr_data, &moreflag); 1584 if (moreflag & T_MORE) { 1585 /* Drop this packet - we have no more space. */ 1586 if (debugging) 1587 fprintf(stderr, 1588 "handle_reply: recvd packet with T_MORE flag set\n"); 1589 goto done; 1590 } 1591 } while (res < 0 && (t_errno == TSYSERR && errno == EINTR)); 1592 if (res < 0) { 1593 if (t_errno == TLOOK) { 1594 if (debugging) 1595 fprintf(stderr, 1596 "handle_reply: t_rcvudata returned %d, t_errno TLOOK\n", res); 1597 (void) t_rcvuderr(fd, (struct t_uderr *)NULL); 1598 } 1599 1600 if (debugging) 1601 fprintf(stderr, 1602 "handle_reply: t_rcvudata returned %d, t_errno %d, errno %d\n", 1603 res, t_errno, errno); 1604 1605 goto done; 1606 } 1607 1608 inlen = tr_data->udata.len; 1609 uaddr = taddr2uaddr(nconf, &tr_data->addr); 1610 if (uaddr == NULL) 1611 goto done; 1612 1613 #ifdef DEBUG_MORE 1614 if (debugging) 1615 fprintf(stderr, 1616 "handle_reply: t_rcvudata received %d-byte packet from %s\n", 1617 inlen, uaddr); 1618 #endif 1619 buffer = tr_data->udata.buf; 1620 if (buffer == (char *)NULL) { 1621 goto done; 1622 } 1623 reply_msg.acpted_rply.ar_verf = _null_auth; 1624 reply_msg.acpted_rply.ar_results.where = 0; 1625 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 1626 1627 xdrmem_create(&reply_xdrs, buffer, (uint_t)inlen, XDR_DECODE); 1628 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) { 1629 if (debugging) 1630 (void) fprintf(stderr, 1631 "handle_reply: xdr_replymsg failed\n"); 1632 goto done; 1633 } 1634 fi = forward_find((ulong_t)reply_msg.rm_xid, uaddr); 1635 if (fi == NULL) 1636 goto done; 1637 #ifdef SVC_RUN_DEBUG 1638 if (debugging) { 1639 fprintf(stderr, "handle_reply: reply xid: %d fi addr: %x\n", 1640 reply_msg.rm_xid, fi); 1641 } 1642 #endif 1643 __seterr_reply(&reply_msg, &reply_error); 1644 if (reply_error.re_status != RPC_SUCCESS) { 1645 if (debugging) 1646 (void) fprintf(stderr, "handle_reply: %s\n", 1647 clnt_sperrno(reply_error.re_status)); 1648 send_svcsyserr(xprt, fi); 1649 goto done; 1650 } 1651 pos = XDR_GETPOS(&reply_xdrs); 1652 len = inlen - pos; 1653 a.rmt_args.args = &buffer[pos]; 1654 a.rmt_args.arglen = len; 1655 a.rmt_uaddr = fi->uaddr; 1656 a.rmt_localvers = fi->versnum; 1657 1658 xprt_set_caller(xprt, fi); 1659 /* XXX hack */ 1660 tu_data = &(getbogus_data(xprt)->su_tudata); 1661 1662 tu_data->addr = xprt->xp_rtaddr; 1663 #ifdef SVC_RUN_DEBUG 1664 if (uaddr) 1665 free((void *) uaddr); 1666 uaddr = taddr2uaddr(nconf, svc_getrpccaller(xprt)); 1667 if (debugging) { 1668 fprintf(stderr, "handle_reply: forwarding address %s to %s\n", 1669 a.rmt_uaddr, uaddr ? uaddr : "unknown"); 1670 } 1671 #endif 1672 svc_sendreply(xprt, (xdrproc_t)xdr_rmtcall_result, (char *)&a); 1673 done: 1674 if (uaddr) 1675 free((void *) uaddr); 1676 if (tr_data) 1677 t_free((char *)tr_data, T_UNITDATA); 1678 if ((fi == NULL) || (reply_msg.rm_xid == 0)) { 1679 #ifdef SVC_RUN_DEBUG 1680 if (debugging) { 1681 fprintf(stderr, "handle_reply: NULL xid on exit!\n"); 1682 } 1683 #endif 1684 } else 1685 (void) free_slot_by_xid((ulong_t)reply_msg.rm_xid, fi->uaddr); 1686 } 1687 1688 static void 1689 find_versions(prog, netid, lowvp, highvp) 1690 ulong_t prog; /* Program Number */ 1691 char *netid; /* Transport Provider token */ 1692 ulong_t *lowvp; /* Low version number */ 1693 ulong_t *highvp; /* High version number */ 1694 { 1695 register rpcblist_ptr rbl; 1696 int lowv = 0; 1697 int highv = 0; 1698 1699 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1700 if ((rbl->rpcb_map.r_prog != prog) || 1701 ((rbl->rpcb_map.r_netid != NULL) && 1702 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1703 continue; 1704 if (lowv == 0) { 1705 highv = rbl->rpcb_map.r_vers; 1706 lowv = highv; 1707 } else if (rbl->rpcb_map.r_vers < lowv) { 1708 lowv = rbl->rpcb_map.r_vers; 1709 } else if (rbl->rpcb_map.r_vers > highv) { 1710 highv = rbl->rpcb_map.r_vers; 1711 } 1712 } 1713 *lowvp = lowv; 1714 *highvp = highv; 1715 } 1716 1717 /* 1718 * returns the item with the given program, version number and netid. 1719 * If that version number is not found, it returns the item with that 1720 * program number, so that address is now returned to the caller. The 1721 * caller when makes a call to this program, version number, the call 1722 * will fail and it will return with PROGVERS_MISMATCH. The user can 1723 * then determine the highest and the lowest version number for this 1724 * program using clnt_geterr() and use those program version numbers. 1725 * 1726 * Returns the RPCBLIST for the given prog, vers and netid 1727 */ 1728 static rpcblist_ptr 1729 find_service(prog, vers, netid) 1730 ulong_t prog; /* Program Number */ 1731 ulong_t vers; /* Version Number */ 1732 char *netid; /* Transport Provider token */ 1733 { 1734 register rpcblist_ptr hit = NULL; 1735 register rpcblist_ptr rbl; 1736 1737 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1738 if ((rbl->rpcb_map.r_prog != prog) || 1739 ((rbl->rpcb_map.r_netid != NULL) && 1740 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1741 continue; 1742 hit = rbl; 1743 if (rbl->rpcb_map.r_vers == vers) 1744 break; 1745 } 1746 return (hit); 1747 } 1748 1749 /* 1750 * If the caller is from our zone and we know 1751 * who it is, we return the uid. 1752 */ 1753 uid_t 1754 rpcb_caller_uid(SVCXPRT *transp) 1755 { 1756 ucred_t *uc = alloca(ucred_size()); 1757 static zoneid_t myzone = MIN_ZONEID - 1; 1758 uid_t uid; 1759 1760 if (myzone == MIN_ZONEID - 1) 1761 myzone = getzoneid(); 1762 1763 if (svc_getcallerucred(transp, &uc) != 0 || 1764 (ucred_getzoneid(uc)) != myzone) { 1765 return (-1); 1766 } else { 1767 return (ucred_geteuid(uc)); 1768 } 1769 } 1770 1771 /* 1772 * Copies the name associated with the uid of the caller and returns 1773 * a pointer to it. Similar to getwd(). 1774 */ 1775 char * 1776 getowner(transp, owner) 1777 SVCXPRT *transp; 1778 char *owner; 1779 { 1780 uid_t uid = rpcb_caller_uid(transp); 1781 1782 switch (uid) { 1783 case -1: 1784 return (strcpy(owner, "unknown")); 1785 case 0: 1786 return (strcpy(owner, "superuser")); 1787 default: 1788 (void) sprintf(owner, "%u", uid); 1789 return (owner); 1790 } 1791 } 1792 1793 #ifdef PORTMAP 1794 /* 1795 * Add this to the pmap list only if it is UDP or TCP. 1796 */ 1797 static int 1798 add_pmaplist(arg) 1799 RPCB *arg; 1800 { 1801 pmap pmap; 1802 pmaplist *pml; 1803 int h1, h2, h3, h4, p1, p2; 1804 1805 if (strcmp(arg->r_netid, udptrans) == 0) { 1806 /* It is UDP! */ 1807 pmap.pm_prot = IPPROTO_UDP; 1808 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1809 /* It is TCP */ 1810 pmap.pm_prot = IPPROTO_TCP; 1811 } else 1812 /* Not a IP protocol */ 1813 return (0); 1814 1815 /* interpret the universal address for TCP/IP */ 1816 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d", 1817 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 1818 return (0); 1819 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff); 1820 pmap.pm_prog = arg->r_prog; 1821 pmap.pm_vers = arg->r_vers; 1822 /* 1823 * add to END of list 1824 */ 1825 pml = (pmaplist *) malloc((uint_t)sizeof (pmaplist)); 1826 if (pml == NULL) { 1827 (void) syslog(LOG_ERR, "rpcbind: no memory!\n"); 1828 return (1); 1829 } 1830 pml->pml_map = pmap; 1831 pml->pml_next = NULL; 1832 if (list_pml == NULL) { 1833 list_pml = pml; 1834 } else { 1835 pmaplist *fnd; 1836 1837 /* Attach to the end of the list */ 1838 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next) 1839 ; 1840 fnd->pml_next = pml; 1841 } 1842 return (0); 1843 } 1844 1845 /* 1846 * Delete this from the pmap list only if it is UDP or TCP. 1847 */ 1848 int 1849 del_pmaplist(RPCB *arg) 1850 { 1851 register pmaplist *pml; 1852 pmaplist *prevpml, *fnd; 1853 long prot; 1854 1855 if (strcmp(arg->r_netid, udptrans) == 0) { 1856 /* It is UDP! */ 1857 prot = IPPROTO_UDP; 1858 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1859 /* It is TCP */ 1860 prot = IPPROTO_TCP; 1861 } else if (arg->r_netid[0] == NULL) { 1862 prot = 0; /* Remove all occurrences */ 1863 } else { 1864 /* Not a IP protocol */ 1865 return (0); 1866 } 1867 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) { 1868 if ((pml->pml_map.pm_prog != arg->r_prog) || 1869 (pml->pml_map.pm_vers != arg->r_vers) || 1870 (prot && (pml->pml_map.pm_prot != prot))) { 1871 /* both pml & prevpml move forwards */ 1872 prevpml = pml; 1873 pml = pml->pml_next; 1874 continue; 1875 } 1876 /* found it; pml moves forward, prevpml stays */ 1877 fnd = pml; 1878 pml = pml->pml_next; 1879 if (prevpml == NULL) 1880 list_pml = pml; 1881 else 1882 prevpml->pml_next = pml; 1883 free((void *) fnd); 1884 } 1885 return (0); 1886 } 1887 #endif /* PORTMAP */ 1888