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 fihead = fi; 1275 if (fitail == NULL) 1276 fitail = fi; 1277 1278 fi->flag = 0; 1279 fi->caller_xid = caller_xid; 1280 1281 fi->forward_xid = lastxid; 1282 fi->forward_fd = forward_fd; 1283 1284 /* 1285 * Though uaddr is not allocated here, it will still be freed 1286 * from forward_destroy(). 1287 */ 1288 fi->uaddr = uaddr; 1289 1290 fi->reply_data = NULL; 1291 (void) cond_init(&fi->cv, USYNC_THREAD, NULL); 1292 1293 rpcb_rmtcalls++; 1294 if (rpcb_rmtcalls > rpcb_rmtcalls_max) { 1295 assert(fitail != fi); 1296 (void) cond_signal(&fitail->cv); 1297 } 1298 1299 return (fi); 1300 } 1301 1302 static void 1303 forward_destroy(struct finfo *fi) 1304 { 1305 assert(MUTEX_HELD(&finfo_lock)); 1306 assert(fi->flag & FINFO_ACTIVE); 1307 1308 if (fihead == fi) { 1309 assert(fi->prev == NULL); 1310 fihead = fi->next; 1311 } else { 1312 fi->prev->next = fi->next; 1313 } 1314 1315 if (fitail == fi) { 1316 assert(fi->next == NULL); 1317 fitail = fi->prev; 1318 } else { 1319 fi->next->prev = fi->prev; 1320 } 1321 1322 netbuffree(fi->caller_addr); 1323 free(fi->uaddr); 1324 if (fi->reply_data != NULL) 1325 t_free((char *)fi->reply_data, T_UNITDATA); 1326 (void) cond_destroy(&fi->cv); 1327 1328 free(fi); 1329 1330 rpcb_rmtcalls--; 1331 if (rpcb_rmtcalls > rpcb_rmtcalls_max) { 1332 assert(fitail != NULL); 1333 (void) cond_signal(&fitail->cv); 1334 } 1335 } 1336 1337 static struct finfo * 1338 forward_find(ulong_t reply_xid, char *uaddr) 1339 { 1340 struct finfo *fi; 1341 1342 assert(MUTEX_HELD(&finfo_lock)); 1343 1344 for (fi = fihead; fi != NULL; fi = fi->next) { 1345 if (fi->forward_xid == reply_xid && 1346 strcmp(fi->uaddr, uaddr) == 0) 1347 return (fi); 1348 } 1349 1350 return (NULL); 1351 } 1352 1353 static int 1354 netbufcmp(struct netbuf *n1, struct netbuf *n2) 1355 { 1356 return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); 1357 } 1358 1359 static struct netbuf * 1360 netbufdup(struct netbuf *ap) 1361 { 1362 struct netbuf *np; 1363 1364 np = malloc(sizeof (struct netbuf) + ap->len); 1365 if (np) { 1366 np->maxlen = np->len = ap->len; 1367 np->buf = ((char *)np) + sizeof (struct netbuf); 1368 (void) memcpy(np->buf, ap->buf, ap->len); 1369 } 1370 return (np); 1371 } 1372 1373 static void 1374 netbuffree(struct netbuf *ap) 1375 { 1376 free(ap); 1377 } 1378 1379 static void 1380 handle_reply(svc_input_id_t id, int fd, unsigned int events, void *cookie) 1381 { 1382 struct t_unitdata *tr_data; 1383 int res; 1384 1385 unsigned int inlen; 1386 char *buffer; 1387 XDR reply_xdrs; 1388 1389 struct rpc_msg reply_msg; 1390 unsigned int pos; 1391 unsigned int len; 1392 1393 struct netconfig *nconf; 1394 char *uaddr = NULL; 1395 1396 struct finfo *fi; 1397 1398 tr_data = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, 1399 T_ADDR | T_UDATA); 1400 if (tr_data == NULL) { 1401 syslog(LOG_ERR, "handle_reply: t_alloc failed!"); 1402 return; 1403 } 1404 1405 do { 1406 int moreflag = 0; 1407 1408 if (errno == EINTR) 1409 errno = 0; 1410 res = t_rcvudata(fd, tr_data, &moreflag); 1411 if (moreflag & T_MORE) { 1412 /* Drop this packet - we have no more space. */ 1413 if (debugging) 1414 fprintf(stderr, "handle_reply: recvd packet " 1415 "with T_MORE flag set\n"); 1416 goto done; 1417 } 1418 } while (res < 0 && t_errno == TSYSERR && errno == EINTR); 1419 1420 if (res < 0) { 1421 if (debugging) 1422 fprintf(stderr, "handle_reply: t_rcvudata returned " 1423 "%d, t_errno %d, errno %d\n", res, t_errno, errno); 1424 1425 if (t_errno == TLOOK) 1426 (void) t_rcvuderr(fd, NULL); 1427 1428 goto done; 1429 } 1430 1431 inlen = tr_data->udata.len; 1432 buffer = tr_data->udata.buf; 1433 assert(buffer != NULL); 1434 xdrmem_create(&reply_xdrs, buffer, inlen, XDR_DECODE); 1435 1436 reply_msg.acpted_rply.ar_verf = _null_auth; 1437 reply_msg.acpted_rply.ar_results.where = 0; 1438 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 1439 1440 if (!xdr_replymsg(&reply_xdrs, &reply_msg)) { 1441 xdr_destroy(&reply_xdrs); 1442 if (debugging) 1443 (void) fprintf(stderr, 1444 "handle_reply: xdr_replymsg failed\n"); 1445 goto done; 1446 } 1447 pos = XDR_GETPOS(&reply_xdrs); 1448 xdr_destroy(&reply_xdrs); 1449 1450 len = inlen - pos; 1451 1452 nconf = rpcbind_get_conf((char *)cookie); 1453 if (nconf == NULL) { 1454 syslog(LOG_ERR, "handle_reply: rpcbind_get_conf failed!"); 1455 goto done; 1456 } 1457 uaddr = taddr2uaddr(nconf, &tr_data->addr); 1458 if (uaddr == NULL) { 1459 syslog(LOG_ERR, "handle_reply: taddr2uaddr failed!"); 1460 goto done; 1461 } 1462 1463 (void) mutex_lock(&finfo_lock); 1464 fi = forward_find(reply_msg.rm_xid, uaddr); 1465 if (fi == NULL) { 1466 (void) mutex_unlock(&finfo_lock); 1467 goto done; 1468 } 1469 1470 fi->reply_data = tr_data; 1471 tr_data = NULL; 1472 1473 __seterr_reply(&reply_msg, &fi->reply_error); 1474 1475 fi->res_len = len; 1476 fi->res_val = &buffer[pos]; 1477 1478 (void) cond_signal(&fi->cv); 1479 (void) mutex_unlock(&finfo_lock); 1480 1481 done: 1482 free(uaddr); 1483 if (tr_data) 1484 t_free((char *)tr_data, T_UNITDATA); 1485 } 1486 1487 /* 1488 * prog: Program Number 1489 * netid: Transport Provider token 1490 * lowvp: Low version number 1491 * highvp: High version number 1492 */ 1493 static void 1494 find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp) 1495 { 1496 rpcblist_ptr rbl; 1497 rpcvers_t lowv = 0; 1498 rpcvers_t highv = 0; 1499 1500 assert(RW_LOCK_HELD(&list_rbl_lock)); 1501 1502 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1503 if ((rbl->rpcb_map.r_prog != prog) || 1504 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)) 1505 continue; 1506 if (lowv == 0) { 1507 highv = rbl->rpcb_map.r_vers; 1508 lowv = highv; 1509 } else if (rbl->rpcb_map.r_vers < lowv) { 1510 lowv = rbl->rpcb_map.r_vers; 1511 } else if (rbl->rpcb_map.r_vers > highv) { 1512 highv = rbl->rpcb_map.r_vers; 1513 } 1514 } 1515 1516 *lowvp = lowv; 1517 *highvp = highv; 1518 } 1519 1520 /* 1521 * returns the item with the given program, version number and netid. 1522 * If that version number is not found, it returns the item with that 1523 * program number, so that address is now returned to the caller. The 1524 * caller when makes a call to this program, version number, the call 1525 * will fail and it will return with PROGVERS_MISMATCH. The user can 1526 * then determine the highest and the lowest version number for this 1527 * program using clnt_geterr() and use those program version numbers. 1528 * 1529 * Returns the RPCBLIST for the given prog, vers and netid 1530 * 1531 * prog: Program Number 1532 * vers: Version Number 1533 * netid: Transport Provider token 1534 */ 1535 static rpcblist_ptr 1536 find_service(rpcprog_t prog, rpcvers_t vers, char *netid) 1537 { 1538 rpcblist_ptr hit = NULL; 1539 rpcblist_ptr rbl; 1540 1541 assert(RW_LOCK_HELD(&list_rbl_lock)); 1542 1543 for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) { 1544 if ((rbl->rpcb_map.r_prog != prog) || 1545 (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)) 1546 continue; 1547 hit = rbl; 1548 if (rbl->rpcb_map.r_vers == vers) 1549 break; 1550 } 1551 1552 return (hit); 1553 } 1554 1555 /* 1556 * If the caller is from our zone and we know 1557 * who it is, we return the uid. 1558 */ 1559 uid_t 1560 rpcb_caller_uid(SVCXPRT *transp) 1561 { 1562 ucred_t *uc = alloca(ucred_size()); 1563 1564 if (svc_getcallerucred(transp, &uc) != 0 || 1565 (ucred_getzoneid(uc)) != myzone) { 1566 return (-1); 1567 } else { 1568 return (ucred_geteuid(uc)); 1569 } 1570 } 1571 1572 /* 1573 * Copies the name associated with the uid of the caller and returns 1574 * a pointer to it. Similar to getwd(). 1575 */ 1576 char * 1577 getowner(SVCXPRT *transp, char *owner) 1578 { 1579 uid_t uid = rpcb_caller_uid(transp); 1580 1581 switch (uid) { 1582 case -1: 1583 return (strcpy(owner, "unknown")); 1584 case 0: 1585 return (strcpy(owner, "superuser")); 1586 default: 1587 (void) sprintf(owner, "%u", uid); 1588 return (owner); 1589 } 1590 } 1591 1592 #ifdef PORTMAP 1593 /* 1594 * Add this to the pmap list only if it is UDP or TCP. 1595 */ 1596 static int 1597 add_pmaplist(RPCB *arg) 1598 { 1599 pmap pmap; 1600 pmaplist *pml; 1601 int h1, h2, h3, h4, p1, p2; 1602 1603 if (strcmp(arg->r_netid, udptrans) == 0) { 1604 /* It is UDP! */ 1605 pmap.pm_prot = IPPROTO_UDP; 1606 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1607 /* It is TCP */ 1608 pmap.pm_prot = IPPROTO_TCP; 1609 } else 1610 /* Not a IP protocol */ 1611 return (0); 1612 1613 /* interpret the universal address for TCP/IP */ 1614 if (sscanf(arg->r_addr, "%d.%d.%d.%d.%d.%d", 1615 &h1, &h2, &h3, &h4, &p1, &p2) != 6) 1616 return (0); 1617 pmap.pm_port = ((p1 & 0xff) << 8) + (p2 & 0xff); 1618 pmap.pm_prog = arg->r_prog; 1619 pmap.pm_vers = arg->r_vers; 1620 /* 1621 * add to END of list 1622 */ 1623 pml = (pmaplist *) malloc((uint_t)sizeof (pmaplist)); 1624 if (pml == NULL) { 1625 (void) syslog(LOG_ERR, "rpcbind: no memory!\n"); 1626 return (1); 1627 } 1628 pml->pml_map = pmap; 1629 pml->pml_next = NULL; 1630 1631 (void) rw_wrlock(&list_pml_lock); 1632 if (list_pml == NULL) { 1633 list_pml = pml; 1634 } else { 1635 pmaplist *fnd; 1636 1637 /* Attach to the end of the list */ 1638 for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next) 1639 ; 1640 fnd->pml_next = pml; 1641 } 1642 (void) rw_unlock(&list_pml_lock); 1643 1644 return (0); 1645 } 1646 1647 /* 1648 * Delete this from the pmap list only if it is UDP or TCP. 1649 */ 1650 int 1651 del_pmaplist(RPCB *arg) 1652 { 1653 pmaplist *pml; 1654 pmaplist *prevpml, *fnd; 1655 rpcport_t prot; 1656 1657 if (strcmp(arg->r_netid, udptrans) == 0) { 1658 /* It is UDP! */ 1659 prot = IPPROTO_UDP; 1660 } else if (strcmp(arg->r_netid, tcptrans) == 0) { 1661 /* It is TCP */ 1662 prot = IPPROTO_TCP; 1663 } else if (arg->r_netid[0] == '\0') { 1664 prot = 0; /* Remove all occurrences */ 1665 } else { 1666 /* Not a IP protocol */ 1667 return (0); 1668 } 1669 1670 assert(RW_WRITE_HELD(&list_pml_lock)); 1671 1672 for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) { 1673 if ((pml->pml_map.pm_prog != arg->r_prog) || 1674 (pml->pml_map.pm_vers != arg->r_vers) || 1675 (prot && (pml->pml_map.pm_prot != prot))) { 1676 /* both pml & prevpml move forwards */ 1677 prevpml = pml; 1678 pml = pml->pml_next; 1679 continue; 1680 } 1681 /* found it; pml moves forward, prevpml stays */ 1682 fnd = pml; 1683 pml = pml->pml_next; 1684 if (prevpml == NULL) 1685 list_pml = pml; 1686 else 1687 prevpml->pml_next = pml; 1688 free(fnd); 1689 } 1690 1691 return (0); 1692 } 1693 #endif /* PORTMAP */ 1694