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