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 2007 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 <rpcsvc/svc_dg_priv.h> 53 #include <netconfig.h> 54 #include <sys/param.h> 55 #include <errno.h> 56 #include <zone.h> 57 #include <sys/poll.h> 58 #include <sys/stropts.h> 59 #ifdef PORTMAP 60 #include <netinet/in.h> 61 #include <rpc/pmap_prot.h> 62 #endif /* PORTMAP */ 63 #include <syslog.h> 64 #include <netdir.h> 65 #include <ucred.h> 66 #include <alloca.h> 67 #include <rpcsvc/yp_prot.h> 68 #include <nfs/nfs.h> 69 #include <nfs/nfs_acl.h> 70 #include <rpcsvc/mount.h> 71 #include <nfs/nfs_acl.h> 72 #include <rpc/key_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 #define RPC_BUF_MAX 65536 /* can be raised if required */ 682 683 /* 684 * This is from ../ypcmd/yp_b.h 685 * It does not appear in <rpcsvc/yp_prot.h> 686 */ 687 #define YPBINDPROG ((ulong_t)100007) 688 #define YPBINDPROC_SETDOM ((ulong_t)2) 689 690 void 691 rpcbproc_callit_com(rqstp, transp, reply_type, versnum) 692 struct svc_req *rqstp; 693 SVCXPRT *transp; 694 ulong_t reply_type; /* which proc number */ 695 ulong_t versnum; /* which vers was called */ 696 { 697 register rpcblist_ptr rbl; 698 struct netconfig *nconf; 699 struct netbuf *caller; 700 struct r_rmtcall_args a; 701 char *buf_alloc = NULL; 702 char *outbuf_alloc = NULL; 703 char buf[RPC_BUF_MAX], outbuf[RPC_BUF_MAX]; 704 struct netbuf *na = (struct netbuf *)NULL; 705 struct t_info tinfo; 706 struct t_unitdata tu_data; 707 struct rpc_msg call_msg; 708 struct svc_dg_data *bd; 709 int outlen; 710 uint_t sendsz; 711 XDR outxdr; 712 AUTH *auth; 713 int fd = -1; 714 char *uaddr; 715 struct nd_mergearg ma; 716 int stat; 717 718 if (t_getinfo(transp->xp_fd, &tinfo) == -1) { 719 if (reply_type == RPCBPROC_INDIRECT) 720 svcerr_systemerr(transp); 721 return; 722 } 723 if (tinfo.servtype != T_CLTS) 724 return; /* Only datagram type accepted */ 725 sendsz = __rpc_get_t_size(0, tinfo.tsdu); 726 if (sendsz == 0) { /* data transfer not supported */ 727 if (reply_type == RPCBPROC_INDIRECT) 728 svcerr_systemerr(transp); 729 return; 730 } 731 /* 732 * Should be multiple of 4 for XDR. 733 */ 734 sendsz = ((sendsz + 3) / 4) * 4; 735 if (sendsz > RPC_BUF_MAX) { 736 #ifdef notyet 737 buf_alloc = alloca(sendsz); /* not in IDR2? */ 738 #else 739 buf_alloc = malloc(sendsz); 740 #endif /* notyet */ 741 if (buf_alloc == NULL) { 742 if (debugging) 743 fprintf(stderr, 744 "rpcbproc_callit_com: No Memory!\n"); 745 if (reply_type == RPCBPROC_INDIRECT) 746 svcerr_systemerr(transp); 747 return; 748 } 749 a.rmt_args.args = buf_alloc; 750 } else { 751 a.rmt_args.args = buf; 752 } 753 754 call_msg.rm_xid = 0; /* For error checking purposes */ 755 ma.m_uaddr = NULL; 756 if (!svc_getargs(transp, (xdrproc_t)xdr_rmtcall_args, (char *)&a)) { 757 if (reply_type == RPCBPROC_INDIRECT) 758 svcerr_decode(transp); 759 if (debugging) 760 fprintf(stderr, 761 "rpcbproc_callit_com: svc_getargs failed\n"); 762 goto error; 763 } 764 if (!allow_indirect) 765 goto error; 766 caller = svc_getrpccaller(transp); 767 #ifdef RPCBIND_DEBUG 768 uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller); 769 fprintf(stderr, "%s %s request for (%lu, %lu, %lu, %s) from %s : ", 770 versnum == PMAPVERS ? "pmap_rmtcall" : 771 versnum == RPCBVERS ? "rpcb_rmtcall" : 772 versnum == RPCBVERS4 ? "rpcb_indirect" : "unknown", 773 reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit", 774 a.rmt_prog, a.rmt_vers, a.rmt_proc, transp->xp_netid, 775 uaddr ? uaddr : "unknown"); 776 if (uaddr) 777 free((void *) uaddr); 778 #endif 779 780 /* 781 * Disallow calling rpcbind for certain procedures. 782 * Allow calling NULLPROC - per man page on rpcb_rmtcall(). 783 * switch is in alphabetical order. 784 */ 785 if (a.rmt_proc != NULLPROC) { 786 switch (a.rmt_prog) { 787 case KEY_PROG: 788 if (debugging) 789 fprintf(stderr, 790 "rpcbind: rejecting KEY_PROG(%d)\n", 791 a.rmt_proc); 792 goto error; 793 case MOUNTPROG: 794 if (a.rmt_proc != MOUNTPROC_MNT) 795 break; 796 /* 797 * In Solaris 2.6, the host-based accesss control 798 * is done by the NFS server on each request. 799 * Prior to 2.6 we rely on mountd. 800 */ 801 if (debugging) 802 fprintf(stderr, 803 "rpcbind: rejecting MOUNTPROG(%d)\n", 804 a.rmt_proc); 805 goto error; 806 case NFS_ACL_PROGRAM: 807 if (debugging) 808 fprintf(stderr, 809 "rpcbind: rejecting NFS_ACL_PROGRAM(%d)\n", 810 a.rmt_proc); 811 goto error; 812 case NFS_PROGRAM: 813 /* also NFS3_PROGRAM */ 814 if (debugging) 815 fprintf(stderr, 816 "rpcbind: rejecting NFS_PROGRAM(%d)\n", 817 a.rmt_proc); 818 goto error; 819 case RPCBPROG: 820 /* 821 * Disallow calling rpcbind for certain procedures. 822 * Luckily Portmap set/unset/callit also have same 823 * procedure numbers. So, will not check for those. 824 */ 825 switch (a.rmt_proc) { 826 case RPCBPROC_SET: 827 case RPCBPROC_UNSET: 828 case RPCBPROC_CALLIT: 829 case RPCBPROC_INDIRECT: 830 if (reply_type == RPCBPROC_INDIRECT) 831 svcerr_weakauth(transp); /* XXX */ 832 if (debugging) 833 fprintf(stderr, 834 "rpcbproc_callit_com: calling RPCBPROG procs SET, UNSET, CALLIT, or INDIRECT \ 835 not allowed \n"); 836 goto error; 837 default: 838 /* 839 * Ideally, we should have called rpcb_service() 840 * or pmap_service() with appropriate parameters 841 * instead of going about in a roundabout 842 * manner. Hopefully, this case should happen 843 * rarely. 844 */ 845 break; 846 } 847 break; 848 case RQUOTAPROG: 849 if (debugging) 850 fprintf(stderr, 851 "rpcbind: rejecting RQUOTAPROG(%d)\n", 852 a.rmt_proc); 853 goto error; 854 case YPPASSWDPROG: 855 if (debugging) 856 fprintf(stderr, 857 "rpcbind: rejecting YPPASSWDPROG(%d)\n", 858 a.rmt_proc); 859 goto error; 860 case YPU_PROG: 861 if (debugging) 862 fprintf(stderr, 863 "rpcbind: rejecting YPU_PROG(%d)\n", 864 a.rmt_proc); 865 goto error; 866 case YPBINDPROG: 867 if (a.rmt_proc != YPBINDPROC_SETDOM) 868 break; 869 if (debugging) 870 fprintf(stderr, 871 "rpcbind: rejecting YPBINDPROG(%d)\n", 872 a.rmt_proc); 873 goto error; 874 case YPPROG: 875 switch (a.rmt_proc) { 876 case YPPROC_FIRST: 877 case YPPROC_NEXT: 878 case YPPROC_MATCH: 879 case YPPROC_ALL: 880 if (debugging) 881 fprintf(stderr, 882 "rpcbind: rejecting YPPROG(%d)\n", 883 a.rmt_proc); 884 goto error; 885 default: 886 break; 887 } 888 break; 889 default: 890 break; 891 } 892 } 893 894 rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid); 895 896 rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers, 897 a.rmt_proc, transp->xp_netid, rbl); 898 899 if (rbl == (rpcblist_ptr)NULL) { 900 #ifdef RPCBIND_DEBUG 901 fprintf(stderr, "not found\n"); 902 #endif 903 if (reply_type == RPCBPROC_INDIRECT) 904 svcerr_noprog(transp); 905 goto error; 906 } 907 if (rbl->rpcb_map.r_vers != a.rmt_vers) { 908 #ifdef RPCBIND_DEBUG 909 fprintf(stderr, "version not found\n"); 910 #endif 911 if (reply_type == RPCBPROC_INDIRECT) { 912 ulong_t vers_low, vers_high; 913 914 find_versions(a.rmt_prog, transp->xp_netid, 915 &vers_low, &vers_high); 916 svcerr_progvers(transp, vers_low, vers_high); 917 } 918 goto error; 919 } 920 921 #ifdef RPCBIND_DEBUG 922 fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr); 923 #endif 924 /* 925 * Check whether this entry is valid and a server is present 926 * Mergeaddr() returns NULL if no such entry is present, and 927 * returns "" if the entry was present but the server is not 928 * present (i.e., it crashed). 929 */ 930 if (reply_type == RPCBPROC_INDIRECT) { 931 uaddr = mergeaddr(transp, transp->xp_netid, 932 rbl->rpcb_map.r_addr, NULL); 933 if ((uaddr == (char *)NULL) || uaddr[0] == '\0') { 934 svcerr_noprog(transp); 935 goto error; 936 } else { 937 free((void *) uaddr); 938 } 939 } 940 nconf = rpcbind_get_conf(transp->xp_netid); 941 if (nconf == (struct netconfig *)NULL) { 942 if (reply_type == RPCBPROC_INDIRECT) 943 svcerr_systemerr(transp); 944 if (debugging) 945 fprintf(stderr, 946 "rpcbproc_callit_com: rpcbind_get_conf failed\n"); 947 goto error; 948 } 949 ma.c_uaddr = taddr2uaddr(nconf, caller); 950 ma.s_uaddr = rbl->rpcb_map.r_addr; 951 /* 952 * A mergeaddr operation allocates a string, which it stores in 953 * ma.m_uaddr. It's passed to forward_register() and is 954 * eventually freed by free_slot_*(). 955 */ 956 957 stat = netdir_options(nconf, ND_MERGEADDR, 0, (char *)&ma); 958 free((void *) ma.c_uaddr); 959 if (stat) 960 (void) syslog(LOG_ERR, "netdir_merge failed for %s: %s", 961 nconf->nc_netid, netdir_sperror()); 962 #ifdef ND_DEBUG 963 fprintf(stderr, 964 "rpcbproc_callit_com: s_uaddr = %s, c_uaddr = %s, merged m_uaddr = %s\n", 965 ma.s_uaddr, ma.c_uaddr, ma.m_uaddr); 966 #endif 967 if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) { 968 if (reply_type == RPCBPROC_INDIRECT) 969 svcerr_systemerr(transp); 970 free((void *) ma.m_uaddr); 971 ma.m_uaddr = NULL; 972 goto error; 973 } 974 bd = get_svc_dg_data(transp); 975 call_msg.rm_xid = forward_register(bd->su_xid, 976 caller, fd, ma.m_uaddr, reply_type, versnum); 977 if (call_msg.rm_xid == 0) { 978 /* 979 * A duplicate request for the slow server. Let's not 980 * beat on it any more. 981 */ 982 if (debugging) 983 fprintf(stderr, 984 "rpcbproc_callit_com: duplicate request\n"); 985 free((void *) ma.m_uaddr); 986 ma.m_uaddr = NULL; 987 goto error; 988 } else if (call_msg.rm_xid == (uint32_t)-1) { 989 /* forward_register failed. Perhaps no memory. */ 990 if (debugging) 991 fprintf(stderr, 992 "rpcbproc_callit_com: forward_register failed\n"); 993 free((void *) ma.m_uaddr); 994 ma.m_uaddr = NULL; 995 goto error; 996 } 997 998 #ifdef DEBUG_RMTCALL 999 fprintf(stderr, 1000 "rpcbproc_callit_com: original XID %x, new XID %x\n", 1001 bd->su_xid, call_msg.rm_xid); 1002 #endif 1003 call_msg.rm_direction = CALL; 1004 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 1005 call_msg.rm_call.cb_prog = a.rmt_prog; 1006 call_msg.rm_call.cb_vers = a.rmt_vers; 1007 if (sendsz > RPC_BUF_MAX) { 1008 #ifdef notyet 1009 outbuf_alloc = alloca(sendsz); /* not in IDR2? */ 1010 #else 1011 outbuf_alloc = malloc(sendsz); 1012 #endif /* notyet */ 1013 if (outbuf_alloc == NULL) { 1014 if (reply_type == RPCBPROC_INDIRECT) 1015 svcerr_systemerr(transp); 1016 if (debugging) 1017 fprintf(stderr, 1018 "rpcbproc_callit_com: No memory!\n"); 1019 goto error; 1020 } 1021 xdrmem_create(&outxdr, outbuf_alloc, sendsz, XDR_ENCODE); 1022 } else { 1023 xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE); 1024 } 1025 if (!xdr_callhdr(&outxdr, &call_msg)) { 1026 if (reply_type == RPCBPROC_INDIRECT) 1027 svcerr_systemerr(transp); 1028 if (debugging) 1029 fprintf(stderr, 1030 "rpcbproc_callit_com: xdr_callhdr failed\n"); 1031 goto error; 1032 } 1033 if (!xdr_u_long(&outxdr, &(a.rmt_proc))) { 1034 if (reply_type == RPCBPROC_INDIRECT) 1035 svcerr_systemerr(transp); 1036 if (debugging) 1037 fprintf(stderr, 1038 "rpcbproc_callit_com: xdr_u_long failed\n"); 1039 goto error; 1040 } 1041 1042 if (rqstp->rq_cred.oa_flavor == AUTH_NULL) { 1043 auth = authnone_create(); 1044 } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) { 1045 struct authsys_parms *au; 1046 1047 au = (struct authsys_parms *)rqstp->rq_clntcred; 1048 auth = authsys_create(au->aup_machname, 1049 au->aup_uid, au->aup_gid, 1050 au->aup_len, au->aup_gids); 1051 if (auth == NULL) /* fall back */ 1052 auth = authnone_create(); 1053 } else { 1054 /* we do not support any other authentication scheme */ 1055 if (debugging) 1056 fprintf(stderr, 1057 "rpcbproc_callit_com: oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n"); 1058 if (reply_type == RPCBPROC_INDIRECT) 1059 svcerr_weakauth(transp); /* XXX too strong.. */ 1060 goto error; 1061 } 1062 if (auth == NULL) { 1063 if (reply_type == RPCBPROC_INDIRECT) 1064 svcerr_systemerr(transp); 1065 if (debugging) 1066 fprintf(stderr, 1067 "rpcbproc_callit_com: authwhatever_create returned NULL\n"); 1068 goto error; 1069 } 1070 if (!AUTH_MARSHALL(auth, &outxdr)) { 1071 if (reply_type == RPCBPROC_INDIRECT) 1072 svcerr_systemerr(transp); 1073 AUTH_DESTROY(auth); 1074 if (debugging) 1075 fprintf(stderr, 1076 "rpcbproc_callit_com: AUTH_MARSHALL failed\n"); 1077 goto error; 1078 } 1079 AUTH_DESTROY(auth); 1080 if (!xdr_opaque_parms(&outxdr, &a)) { 1081 if (reply_type == RPCBPROC_INDIRECT) 1082 svcerr_systemerr(transp); 1083 if (debugging) 1084 fprintf(stderr, 1085 "rpcbproc_callit_com: xdr_opaque_parms failed\n"); 1086 goto error; 1087 } 1088 outlen = (int)XDR_GETPOS(&outxdr); 1089 if (outbuf_alloc) 1090 tu_data.udata.buf = outbuf_alloc; 1091 else 1092 tu_data.udata.buf = outbuf; 1093 tu_data.udata.len = outlen; 1094 tu_data.opt.len = 0; 1095 1096 na = uaddr2taddr(nconf, ma.m_uaddr); 1097 if (!na) { 1098 if (reply_type == RPCBPROC_INDIRECT) 1099 svcerr_systemerr(transp); 1100 goto error; 1101 } 1102 tu_data.addr = *na; 1103 1104 if (t_sndudata(fd, &tu_data) == -1) { 1105 if (debugging) 1106 fprintf(stderr, 1107 "rpcbproc_callit_com: t_sndudata failed: t_errno %d, errno %d\n", 1108 t_errno, errno); 1109 if (reply_type == RPCBPROC_INDIRECT) 1110 svcerr_systemerr(transp); 1111 goto error; 1112 } 1113 goto out; 1114 1115 error: 1116 if ((call_msg.rm_xid != 0) && (ma.m_uaddr != NULL)) 1117 (void) free_slot_by_xid(call_msg.rm_xid, ma.m_uaddr); 1118 out: 1119 if (buf_alloc) 1120 free((void *) buf_alloc); 1121 if (outbuf_alloc) 1122 free((void *) outbuf_alloc); 1123 if (na) 1124 netdir_free((char *)na, ND_ADDR); 1125 } 1126 1127 #define NFORWARD 64 1128 #define MAXTIME_OFF 300 /* 5 minutes */ 1129 1130 struct finfo { 1131 int flag; 1132 #define FINFO_ACTIVE 0x1 1133 ulong_t caller_xid; 1134 struct netbuf *caller_addr; 1135 ulong_t forward_xid; 1136 int forward_fd; 1137 char *uaddr; 1138 ulong_t reply_type; 1139 ulong_t versnum; 1140 time_t time; 1141 }; 1142 static struct finfo FINFO[NFORWARD]; 1143 /* 1144 * Makes an entry into the FIFO for the given request. 1145 * If duplicate request, returns a 0, else returns the xid of its call. 1146 */ 1147 static ulong_t 1148 forward_register(caller_xid, caller_addr, forward_fd, uaddr, 1149 reply_type, versnum) 1150 ulong_t caller_xid; 1151 struct netbuf *caller_addr; 1152 int forward_fd; 1153 char *uaddr; 1154 ulong_t reply_type; 1155 ulong_t versnum; 1156 { 1157 int i; 1158 int j = 0; 1159 time_t min_time, time_now; 1160 static ulong_t lastxid; 1161 int entry = -1; 1162 1163 min_time = FINFO[0].time; 1164 time_now = time((time_t *)0); 1165 /* 1166 * initialization: once this has happened, lastxid will 1167 * - always be a multiple of NFORWARD (which has to be a power of 2), 1168 * - never be 0 again, 1169 * - never be (ulong_t)(-NFORWARD) 1170 * when entering or returning from this function. 1171 */ 1172 if (lastxid == 0) { 1173 lastxid = time_now * NFORWARD; 1174 /* 1175 * avoid lastxid wraparound to 0, 1176 * and generating a forward_xid of -1 1177 */ 1178 if (lastxid >= (ulong_t)(-NFORWARD)) 1179 lastxid = NFORWARD; 1180 } 1181 1182 /* 1183 * Check if it is an duplicate entry. Then, 1184 * try to find an empty slot. If not available, then 1185 * use the slot with the earliest time. 1186 */ 1187 for (i = 0; i < NFORWARD; i++) { 1188 if (FINFO[i].flag & FINFO_ACTIVE) { 1189 if ((FINFO[i].caller_xid == caller_xid) && 1190 (FINFO[i].reply_type == reply_type) && 1191 (FINFO[i].versnum == versnum) && 1192 (!netbufcmp(FINFO[i].caller_addr, 1193 caller_addr))) { 1194 FINFO[i].time = time((time_t *)0); 1195 return (0); /* Duplicate entry */ 1196 } else { 1197 /* Should we wait any longer */ 1198 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 1199 (void) free_slot_by_index(i); 1200 } 1201 } 1202 if (entry == -1) { 1203 if ((FINFO[i].flag & FINFO_ACTIVE) == 0) { 1204 entry = i; 1205 } else if (FINFO[i].time < min_time) { 1206 j = i; 1207 min_time = FINFO[i].time; 1208 } 1209 } 1210 } 1211 if (entry != -1) { 1212 /* use this empty slot */ 1213 j = entry; 1214 } else { 1215 (void) free_slot_by_index(j); 1216 } 1217 if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) { 1218 return ((ulong_t)-1); 1219 } 1220 rpcb_rmtcalls++; /* no of pending calls */ 1221 FINFO[j].flag = FINFO_ACTIVE; 1222 FINFO[j].reply_type = reply_type; 1223 FINFO[j].versnum = versnum; 1224 FINFO[j].time = time_now; 1225 FINFO[j].caller_xid = caller_xid; 1226 FINFO[j].forward_fd = forward_fd; 1227 /* 1228 * Though uaddr is not allocated here, it will still be freed 1229 * from free_slot_*(). 1230 */ 1231 FINFO[j].uaddr = uaddr; 1232 lastxid = lastxid + NFORWARD; 1233 /* avoid lastxid wraparound to 0, and generating a forward_xid of -1 */ 1234 if (lastxid >= (ulong_t)(-NFORWARD)) 1235 lastxid = NFORWARD; 1236 1237 FINFO[j].forward_xid = lastxid + j; /* encode slot */ 1238 return (FINFO[j].forward_xid); /* forward on this xid */ 1239 } 1240 1241 static struct finfo * 1242 forward_find(reply_xid, uaddr) 1243 ulong_t reply_xid; 1244 char *uaddr; 1245 { 1246 int i; 1247 1248 i = reply_xid % NFORWARD; 1249 if (i < 0) 1250 i += NFORWARD; 1251 if ((FINFO[i].flag & FINFO_ACTIVE) && 1252 (strcmp(FINFO[i].uaddr, uaddr) == 0) && 1253 (FINFO[i].forward_xid == reply_xid)) { 1254 return (&FINFO[i]); 1255 } 1256 return (NULL); 1257 } 1258 1259 static int 1260 free_slot_by_xid(xid, uaddr) 1261 ulong_t xid; 1262 char *uaddr; 1263 { 1264 int entry; 1265 1266 if (forward_find(xid, uaddr)) { 1267 entry = xid % NFORWARD; 1268 if (entry < 0) 1269 entry += NFORWARD; 1270 return (free_slot_by_index(entry)); 1271 } 1272 return (0); 1273 } 1274 1275 static int 1276 free_slot_by_index(index) 1277 int index; 1278 { 1279 struct finfo *fi; 1280 1281 fi = &FINFO[index]; 1282 if (fi->flag & FINFO_ACTIVE) { 1283 netbuffree(fi->caller_addr); 1284 free((void *) fi->uaddr); 1285 fi->flag &= ~FINFO_ACTIVE; 1286 rpcb_rmtcalls--; 1287 return (1); 1288 } 1289 return (0); 1290 } 1291 1292 static int 1293 netbufcmp(n1, n2) 1294 struct netbuf *n1, *n2; 1295 { 1296 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); 1297 } 1298 1299 static struct netbuf * 1300 netbufdup(ap) 1301 register struct netbuf *ap; 1302 { 1303 register struct netbuf *np; 1304 1305 np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len); 1306 if (np) { 1307 np->maxlen = np->len = ap->len; 1308 np->buf = ((char *)np) + sizeof (struct netbuf); 1309 (void) memcpy(np->buf, ap->buf, ap->len); 1310 } 1311 return (np); 1312 } 1313 1314 static void 1315 netbuffree(ap) 1316 register struct netbuf *ap; 1317 { 1318 free((void *) ap); 1319 } 1320 1321 /* 1322 * active_fd is used to determine whether an entry in svc_pollfd is: 1323 * 1. not a forward fd (should be polled) 1324 * 2. an active forward fd (should be polled) 1325 * 3. an inactive forward fd (should not be polled) 1326 */ 1327 static bool_t 1328 active_fd(fd) 1329 int fd; 1330 { 1331 int i; 1332 time_t time_now; 1333 1334 if (find_rmtcallxprt_by_fd(fd) == (SVCXPRT *)NULL) 1335 return (TRUE); 1336 if (rpcb_rmtcalls == 0) 1337 return (FALSE); 1338 time_now = time((time_t *)0); 1339 for (i = 0; i < NFORWARD; i++) 1340 if (FINFO[i].forward_fd == fd) { 1341 if (FINFO[i].flag & FINFO_ACTIVE) { 1342 /* Should we wait any longer */ 1343 if ((time_now - FINFO[i].time) > MAXTIME_OFF) 1344 (void) free_slot_by_index(i); 1345 else 1346 return (TRUE); 1347 } 1348 } 1349 return (FALSE); 1350 } 1351 1352 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) 1353 1354 void 1355 my_svc_run() 1356 { 1357 size_t nfds; 1358 struct pollfd pollfds[FD_SETSIZE]; 1359 int poll_ret, check_ret; 1360 #ifdef SVC_RUN_DEBUG 1361 int i; 1362 #endif 1363 register struct pollfd *p; 1364 1365 for (;;) { 1366 { 1367 register pollfd_t *in; 1368 register int n; /* loop counter */ 1369 1370 /* 1371 * compress the sparse svc_pollfd strcutre 1372 * into pollfds 1373 */ 1374 memset(pollfds, 0, sizeof (pollfds)); 1375 p = pollfds; 1376 for (in = svc_pollfd, n = 0; n < svc_max_pollfd; 1377 n++, in++) { 1378 if ((in->fd >= 0) && active_fd(in->fd)) { 1379 p->fd = in->fd; 1380 p->events = MASKVAL; 1381 p->revents = 0; 1382 p++; 1383 } 1384 } 1385 nfds = p - pollfds; 1386 } 1387 poll_ret = 0; 1388 #ifdef SVC_RUN_DEBUG 1389 if (debugging) { 1390 fprintf(stderr, "polling for read on fd < "); 1391 for (i = 0, p = pollfds; i < nfds; i++, p++) 1392 if (p->events) 1393 fprintf(stderr, "%d ", p->fd); 1394 fprintf(stderr, ">\n"); 1395 } 1396 #endif 1397 switch (poll_ret = poll(pollfds, nfds, INFTIM)) { 1398 case -1: 1399 /* 1400 * We ignore all errors, continuing with the assumption 1401 * that it was set by the signal handlers (or any 1402 * other outside event) and not caused by poll(). 1403 * If it was our refresh signal, call the refresh 1404 * function. 1405 */ 1406 if (sigrefresh) { 1407 sigrefresh = 0; 1408 rpcb_check_init(); 1409 } 1410 case 0: 1411 continue; 1412 default: 1413 #ifdef SVC_RUN_DEBUG 1414 if (debugging) { 1415 fprintf(stderr, "poll returned read fds < "); 1416 for (i = 0, p = pollfds; i < nfds; i++, p++) 1417 if (p->revents) 1418 fprintf(stderr, "%d ", p->fd); 1419 fprintf(stderr, ">\n"); 1420 } 1421 #endif 1422 /* 1423 * If we found as many replies on callback fds 1424 * as the number of descriptors selectable which 1425 * poll() returned, there can be no more so we 1426 * don't call svc_getreq_poll. Otherwise, there 1427 * must be another so we must call svc_getreq_poll. 1428 */ 1429 if ((check_ret = check_rmtcalls(pollfds, nfds)) == 1430 poll_ret) 1431 continue; 1432 svc_getreq_poll(pollfds, poll_ret-check_ret); 1433 } 1434 } 1435 } 1436 1437 static int 1438 check_rmtcalls(pfds, nfds) 1439 struct pollfd *pfds; 1440 int nfds; 1441 { 1442 int j, ncallbacks_found = 0; 1443 SVCXPRT *xprt; 1444 1445 /* 1446 * This fd will not be polled if rpcb_rmtcalls == 0 1447 */ 1448 if (rpcb_rmtcalls == 0) 1449 return (0); 1450 1451 for (j = 0; j < nfds; j++) { 1452 if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) { 1453 if (pfds[j].revents) { 1454 ncallbacks_found++; 1455 #ifdef DEBUG_RMTCALL 1456 if (debugging) 1457 fprintf(stderr, 1458 "my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n", 1459 pfds[j].fd, xprt->xp_netid); 1460 #endif 1461 handle_reply(pfds[j].fd, xprt); 1462 pfds[j].revents = 0; 1463 } 1464 } 1465 } 1466 return (ncallbacks_found); 1467 } 1468 1469 static void 1470 xprt_set_caller(xprt, fi) 1471 SVCXPRT *xprt; 1472 struct finfo *fi; 1473 { 1474 struct svc_dg_data *bd; 1475 1476 *(svc_getrpccaller(xprt)) = *(fi->caller_addr); 1477 bd = get_svc_dg_data(xprt); 1478 bd->su_xid = fi->caller_xid; /* set xid on reply */ 1479 } 1480 1481 /* 1482 * Call svcerr_systemerr() only if RPCBVERS4 1483 */ 1484 static void 1485 send_svcsyserr(xprt, fi) 1486 SVCXPRT *xprt; 1487 struct finfo *fi; 1488 { 1489 if (fi->reply_type == RPCBPROC_INDIRECT) { 1490 xprt_set_caller(xprt, fi); 1491 svcerr_systemerr(xprt); 1492 } 1493 } 1494 1495 static void 1496 handle_reply(fd, xprt) 1497 int fd; 1498 SVCXPRT *xprt; 1499 { 1500 XDR reply_xdrs; 1501 struct rpc_msg reply_msg; 1502 struct rpc_err reply_error; 1503 char *buffer; 1504 struct finfo *fi = NULL; 1505 int inlen, pos, len, res, i; 1506 struct r_rmtcall_args a; 1507 struct t_unitdata *tr_data = NULL, *tu_data; 1508 struct netconfig *nconf = NULL; 1509 char *uaddr = NULL; 1510 1511 nconf = rpcbind_get_conf(xprt->xp_netid); 1512 if (nconf == NULL) { 1513 #ifdef SVC_RUN_DEBUG 1514 if (debugging) 1515 fprintf(stderr, "handle_reply: null xp_netid\n"); 1516 #endif 1517 goto done; 1518 } 1519 /* 1520 * If this fd is not active on the forward list, ignore it 1521 * If the svc_pollfd structure has multiple settings 1522 * of the same fd, then it will enter handle_reply() for the first one, 1523 * set FINFO_ACTIVE false and then get another call to handle_reply() 1524 * with the same, now inactive, fd. 1525 */ 1526 1527 for (i = 0; i < NFORWARD; i++) { 1528 if ((FINFO[i].forward_fd == fd) && 1529 (FINFO[i].flag & FINFO_ACTIVE)) 1530 break; 1531 } 1532 1533 if (i == NFORWARD) { 1534 #ifdef SVC_RUN_DEBUG 1535 if (debugging) { 1536 fprintf(stderr, "Unsolicited message on rmtcall fd\n"); 1537 } 1538 #endif 1539 return; 1540 } 1541 1542 reply_msg.rm_xid = 0; /* for easier error handling */ 1543 tr_data = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, 1544 T_ADDR | T_UDATA); 1545 if (tr_data == (struct t_unitdata *)NULL) { 1546 if (debugging) 1547 fprintf(stderr, 1548 "handle_reply: t_alloc T_UNITDATA failed\n"); 1549 goto done; 1550 } 1551 do { 1552 int moreflag; 1553 1554 moreflag = 0; 1555 if (errno == EINTR) 1556 errno = 0; 1557 res = t_rcvudata(fd, tr_data, &moreflag); 1558 if (moreflag & T_MORE) { 1559 /* Drop this packet - we have no more space. */ 1560 if (debugging) 1561 fprintf(stderr, 1562 "handle_reply: recvd packet with T_MORE flag set\n"); 1563 goto done; 1564 } 1565 } while (res < 0 && (t_errno == TSYSERR && errno == EINTR)); 1566 if (res < 0) { 1567 if (t_errno == TLOOK) { 1568 if (debugging) 1569 fprintf(stderr, 1570 "handle_reply: t_rcvudata returned %d, t_errno TLOOK\n", res); 1571 (void) t_rcvuderr(fd, (struct t_uderr *)NULL); 1572 } 1573 1574 if (debugging) 1575 fprintf(stderr, 1576 "handle_reply: t_rcvudata returned %d, t_errno %d, errno %d\n", 1577 res, t_errno, errno); 1578 1579 goto done; 1580 } 1581 1582 inlen = tr_data->udata.len; 1583 uaddr = taddr2uaddr(nconf, &tr_data->addr); 1584 if (uaddr == NULL) 1585 goto done; 1586 1587 #ifdef DEBUG_MORE 1588 if (debugging) 1589 fprintf(stderr, 1590 "handle_reply: t_rcvudata received %d-byte packet from %s\n", 1591 inlen, uaddr); 1592 #endif 1593 buffer = tr_data->udata.buf; 1594 if (buffer == (char *)NULL) { 1595 goto done; 1596 } 1597 reply_msg.acpted_rply.ar_verf = _null_auth; 1598 reply_msg.acpted_rply.ar_results.where = 0; 1599 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 1600 1601 xdrmem_create(&reply_xdrs, buffer, (uint_t)inlen, XDR_DECODE); 1602 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) { 1603 if (debugging) 1604 (void) fprintf(stderr, 1605 "handle_reply: xdr_replymsg failed\n"); 1606 goto done; 1607 } 1608 fi = forward_find((ulong_t)reply_msg.rm_xid, uaddr); 1609 if (fi == NULL) 1610 goto done; 1611 #ifdef SVC_RUN_DEBUG 1612 if (debugging) { 1613 fprintf(stderr, "handle_reply: reply xid: %d fi addr: %x\n", 1614 reply_msg.rm_xid, fi); 1615 } 1616 #endif 1617 __seterr_reply(&reply_msg, &reply_error); 1618 if (reply_error.re_status != RPC_SUCCESS) { 1619 if (debugging) 1620 (void) fprintf(stderr, "handle_reply: %s\n", 1621 clnt_sperrno(reply_error.re_status)); 1622 send_svcsyserr(xprt, fi); 1623 goto done; 1624 } 1625 pos = XDR_GETPOS(&reply_xdrs); 1626 len = inlen - pos; 1627 a.rmt_args.args = &buffer[pos]; 1628 a.rmt_args.arglen = len; 1629 a.rmt_uaddr = fi->uaddr; 1630 a.rmt_localvers = fi->versnum; 1631 1632 xprt_set_caller(xprt, fi); 1633 /* XXX hack */ 1634 tu_data = &(get_svc_dg_data(xprt)->su_tudata); 1635 1636 tu_data->addr = xprt->xp_rtaddr; 1637 #ifdef SVC_RUN_DEBUG 1638 if (uaddr) 1639 free((void *) uaddr); 1640 uaddr = taddr2uaddr(nconf, svc_getrpccaller(xprt)); 1641 if (debugging) { 1642 fprintf(stderr, "handle_reply: forwarding address %s to %s\n", 1643 a.rmt_uaddr, uaddr ? uaddr : "unknown"); 1644 } 1645 #endif 1646 svc_sendreply(xprt, (xdrproc_t)xdr_rmtcall_result, (char *)&a); 1647 done: 1648 if (uaddr) 1649 free((void *) uaddr); 1650 if (tr_data) 1651 t_free((char *)tr_data, T_UNITDATA); 1652 if ((fi == NULL) || (reply_msg.rm_xid == 0)) { 1653 #ifdef SVC_RUN_DEBUG 1654 if (debugging) { 1655 fprintf(stderr, "handle_reply: NULL xid on exit!\n"); 1656 } 1657 #endif 1658 } else 1659 (void) free_slot_by_xid((ulong_t)reply_msg.rm_xid, fi->uaddr); 1660 } 1661 1662 static void 1663 find_versions(prog, netid, lowvp, highvp) 1664 ulong_t prog; /* Program Number */ 1665 char *netid; /* Transport Provider token */ 1666 ulong_t *lowvp; /* Low version number */ 1667 ulong_t *highvp; /* High version number */ 1668 { 1669 register rpcblist_ptr rbl; 1670 int lowv = 0; 1671 int highv = 0; 1672 1673 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1674 if ((rbl->rpcb_map.r_prog != prog) || 1675 ((rbl->rpcb_map.r_netid != NULL) && 1676 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1677 continue; 1678 if (lowv == 0) { 1679 highv = rbl->rpcb_map.r_vers; 1680 lowv = highv; 1681 } else if (rbl->rpcb_map.r_vers < lowv) { 1682 lowv = rbl->rpcb_map.r_vers; 1683 } else if (rbl->rpcb_map.r_vers > highv) { 1684 highv = rbl->rpcb_map.r_vers; 1685 } 1686 } 1687 *lowvp = lowv; 1688 *highvp = highv; 1689 } 1690 1691 /* 1692 * returns the item with the given program, version number and netid. 1693 * If that version number is not found, it returns the item with that 1694 * program number, so that address is now returned to the caller. The 1695 * caller when makes a call to this program, version number, the call 1696 * will fail and it will return with PROGVERS_MISMATCH. The user can 1697 * then determine the highest and the lowest version number for this 1698 * program using clnt_geterr() and use those program version numbers. 1699 * 1700 * Returns the RPCBLIST for the given prog, vers and netid 1701 */ 1702 static rpcblist_ptr 1703 find_service(prog, vers, netid) 1704 ulong_t prog; /* Program Number */ 1705 ulong_t vers; /* Version Number */ 1706 char *netid; /* Transport Provider token */ 1707 { 1708 register rpcblist_ptr hit = NULL; 1709 register rpcblist_ptr rbl; 1710 1711 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1712 if ((rbl->rpcb_map.r_prog != prog) || 1713 ((rbl->rpcb_map.r_netid != NULL) && 1714 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0))) 1715 continue; 1716 hit = rbl; 1717 if (rbl->rpcb_map.r_vers == vers) 1718 break; 1719 } 1720 return (hit); 1721 } 1722 1723 /* 1724 * If the caller is from our zone and we know 1725 * who it is, we return the uid. 1726 */ 1727 uid_t 1728 rpcb_caller_uid(SVCXPRT *transp) 1729 { 1730 ucred_t *uc = alloca(ucred_size()); 1731 static zoneid_t myzone = MIN_ZONEID - 1; 1732 uid_t uid; 1733 1734 if (myzone == MIN_ZONEID - 1) 1735 myzone = getzoneid(); 1736 1737 if (svc_getcallerucred(transp, &uc) != 0 || 1738 (ucred_getzoneid(uc)) != myzone) { 1739 return (-1); 1740 } else { 1741 return (ucred_geteuid(uc)); 1742 } 1743 } 1744 1745 /* 1746 * Copies the name associated with the uid of the caller and returns 1747 * a pointer to it. Similar to getwd(). 1748 */ 1749 char * 1750 getowner(transp, owner) 1751 SVCXPRT *transp; 1752 char *owner; 1753 { 1754 uid_t uid = rpcb_caller_uid(transp); 1755 1756 switch (uid) { 1757 case -1: 1758 return (strcpy(owner, "unknown")); 1759 case 0: 1760 return (strcpy(owner, "superuser")); 1761 default: 1762 (void) sprintf(owner, "%u", uid); 1763 return (owner); 1764 } 1765 } 1766 1767 #ifdef PORTMAP 1768 /* 1769 * Add this to the pmap list only if it is UDP or TCP. 1770 */ 1771 static int 1772 add_pmaplist(arg) 1773 RPCB *arg; 1774 { 1775 pmap pmap; 1776 pmaplist *pml; 1777 int h1, h2, h3, h4, p1, p2; 1778 1779 if (strcmp(arg->r_netid, udptrans) == 0) { 1780 /* It is UDP! */ 1781 pmap.pm_prot = IPPROTO_UDP; 1782 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1783 /* It is TCP */ 1784 pmap.pm_prot = IPPROTO_TCP; 1785 } else 1786 /* Not a IP protocol */ 1787 return (0); 1788 1789 /* interpret the universal address for TCP/IP */ 1790 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d", 1791 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 1792 return (0); 1793 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff); 1794 pmap.pm_prog = arg->r_prog; 1795 pmap.pm_vers = arg->r_vers; 1796 /* 1797 * add to END of list 1798 */ 1799 pml = (pmaplist *) malloc((uint_t)sizeof (pmaplist)); 1800 if (pml == NULL) { 1801 (void) syslog(LOG_ERR, "rpcbind: no memory!\n"); 1802 return (1); 1803 } 1804 pml->pml_map = pmap; 1805 pml->pml_next = NULL; 1806 if (list_pml == NULL) { 1807 list_pml = pml; 1808 } else { 1809 pmaplist *fnd; 1810 1811 /* Attach to the end of the list */ 1812 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next) 1813 ; 1814 fnd->pml_next = pml; 1815 } 1816 return (0); 1817 } 1818 1819 /* 1820 * Delete this from the pmap list only if it is UDP or TCP. 1821 */ 1822 int 1823 del_pmaplist(RPCB *arg) 1824 { 1825 register pmaplist *pml; 1826 pmaplist *prevpml, *fnd; 1827 long prot; 1828 1829 if (strcmp(arg->r_netid, udptrans) == 0) { 1830 /* It is UDP! */ 1831 prot = IPPROTO_UDP; 1832 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1833 /* It is TCP */ 1834 prot = IPPROTO_TCP; 1835 } else if (arg->r_netid[0] == NULL) { 1836 prot = 0; /* Remove all occurrences */ 1837 } else { 1838 /* Not a IP protocol */ 1839 return (0); 1840 } 1841 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) { 1842 if ((pml->pml_map.pm_prog != arg->r_prog) || 1843 (pml->pml_map.pm_vers != arg->r_vers) || 1844 (prot && (pml->pml_map.pm_prot != prot))) { 1845 /* both pml & prevpml move forwards */ 1846 prevpml = pml; 1847 pml = pml->pml_next; 1848 continue; 1849 } 1850 /* found it; pml moves forward, prevpml stays */ 1851 fnd = pml; 1852 pml = pml->pml_next; 1853 if (prevpml == NULL) 1854 list_pml = pml; 1855 else 1856 prevpml->pml_next = pml; 1857 free((void *) fnd); 1858 } 1859 return (0); 1860 } 1861 #endif /* PORTMAP */ 1862