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