1 /* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 2010, Oracle America, Inc. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * - Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * - Neither the name of the "Oracle America, Inc." nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /* 33 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34 */ 35 36 #include <sys/cdefs.h> 37 /* 38 * rpcb_clnt.c 39 * interface to rpcbind rpc service. 40 * 41 * Copyright (C) 1988, Sun Microsystems, Inc. 42 */ 43 44 #include "opt_inet6.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #include <sys/proc.h> 51 #include <sys/socket.h> 52 #include <sys/socketvar.h> 53 54 #include <rpc/rpc.h> 55 #include <rpc/rpcb_clnt.h> 56 #include <rpc/rpcb_prot.h> 57 58 #include <rpc/rpc_com.h> 59 60 static struct timeval tottimeout = { 60, 0 }; 61 static const char nullstring[] = "\000"; 62 63 static CLIENT *local_rpcb(void); 64 65 #if 0 66 67 static const struct timeval rmttimeout = { 3, 0 }; 68 static struct timeval rpcbrmttime = { 15, 0 }; 69 70 #define CACHESIZE 6 71 72 struct address_cache { 73 char *ac_host; 74 char *ac_netid; 75 char *ac_uaddr; 76 struct netbuf *ac_taddr; 77 struct address_cache *ac_next; 78 }; 79 80 static struct address_cache *front; 81 static int cachesize; 82 83 #define CLCR_GET_RPCB_TIMEOUT 1 84 #define CLCR_SET_RPCB_TIMEOUT 2 85 86 87 extern int __rpc_lowvers; 88 89 static struct address_cache *check_cache(const char *, const char *); 90 static void delete_cache(struct netbuf *); 91 static void add_cache(const char *, const char *, struct netbuf *, char *); 92 static CLIENT *getclnthandle(const char *, const struct netconfig *, char **); 93 static CLIENT *local_rpcb(void); 94 static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *); 95 96 /* 97 * This routine adjusts the timeout used for calls to the remote rpcbind. 98 * Also, this routine can be used to set the use of portmapper version 2 99 * only when doing rpc_broadcasts 100 * These are private routines that may not be provided in future releases. 101 */ 102 bool_t 103 __rpc_control(request, info) 104 int request; 105 void *info; 106 { 107 switch (request) { 108 case CLCR_GET_RPCB_TIMEOUT: 109 *(struct timeval *)info = tottimeout; 110 break; 111 case CLCR_SET_RPCB_TIMEOUT: 112 tottimeout = *(struct timeval *)info; 113 break; 114 case CLCR_SET_LOWVERS: 115 __rpc_lowvers = *(int *)info; 116 break; 117 case CLCR_GET_LOWVERS: 118 *(int *)info = __rpc_lowvers; 119 break; 120 default: 121 return (FALSE); 122 } 123 return (TRUE); 124 } 125 126 /* 127 * It might seem that a reader/writer lock would be more reasonable here. 128 * However because getclnthandle(), the only user of the cache functions, 129 * may do a delete_cache() operation if a check_cache() fails to return an 130 * address useful to clnt_tli_create(), we may as well use a mutex. 131 */ 132 /* 133 * As it turns out, if the cache lock is *not* a reader/writer lock, we will 134 * block all clnt_create's if we are trying to connect to a host that's down, 135 * since the lock will be held all during that time. 136 */ 137 138 /* 139 * The routines check_cache(), add_cache(), delete_cache() manage the 140 * cache of rpcbind addresses for (host, netid). 141 */ 142 143 static struct address_cache * 144 check_cache(host, netid) 145 const char *host, *netid; 146 { 147 struct address_cache *cptr; 148 149 /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 150 151 for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 152 if (!strcmp(cptr->ac_host, host) && 153 !strcmp(cptr->ac_netid, netid)) { 154 #ifdef ND_DEBUG 155 fprintf(stderr, "Found cache entry for %s: %s\n", 156 host, netid); 157 #endif 158 return (cptr); 159 } 160 } 161 return ((struct address_cache *) NULL); 162 } 163 164 static void 165 delete_cache(addr) 166 struct netbuf *addr; 167 { 168 struct address_cache *cptr, *prevptr = NULL; 169 170 /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ 171 for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { 172 if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) { 173 free(cptr->ac_host); 174 free(cptr->ac_netid); 175 free(cptr->ac_taddr->buf); 176 free(cptr->ac_taddr); 177 if (cptr->ac_uaddr) 178 free(cptr->ac_uaddr); 179 if (prevptr) 180 prevptr->ac_next = cptr->ac_next; 181 else 182 front = cptr->ac_next; 183 free(cptr); 184 cachesize--; 185 break; 186 } 187 prevptr = cptr; 188 } 189 } 190 191 static void 192 add_cache(host, netid, taddr, uaddr) 193 const char *host, *netid; 194 char *uaddr; 195 struct netbuf *taddr; 196 { 197 struct address_cache *ad_cache, *cptr, *prevptr; 198 199 ad_cache = (struct address_cache *) 200 malloc(sizeof (struct address_cache)); 201 if (!ad_cache) { 202 return; 203 } 204 ad_cache->ac_host = strdup(host); 205 ad_cache->ac_netid = strdup(netid); 206 ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL; 207 ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf)); 208 if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr || 209 (uaddr && !ad_cache->ac_uaddr)) { 210 goto out; 211 } 212 ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len; 213 ad_cache->ac_taddr->buf = (char *) malloc(taddr->len); 214 if (ad_cache->ac_taddr->buf == NULL) { 215 out: 216 if (ad_cache->ac_host) 217 free(ad_cache->ac_host); 218 if (ad_cache->ac_netid) 219 free(ad_cache->ac_netid); 220 if (ad_cache->ac_uaddr) 221 free(ad_cache->ac_uaddr); 222 if (ad_cache->ac_taddr) 223 free(ad_cache->ac_taddr); 224 free(ad_cache); 225 return; 226 } 227 memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); 228 #ifdef ND_DEBUG 229 fprintf(stderr, "Added to cache: %s : %s\n", host, netid); 230 #endif 231 232 /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ 233 234 rwlock_wrlock(&rpcbaddr_cache_lock); 235 if (cachesize < CACHESIZE) { 236 ad_cache->ac_next = front; 237 front = ad_cache; 238 cachesize++; 239 } else { 240 /* Free the last entry */ 241 cptr = front; 242 prevptr = NULL; 243 while (cptr->ac_next) { 244 prevptr = cptr; 245 cptr = cptr->ac_next; 246 } 247 248 #ifdef ND_DEBUG 249 fprintf(stderr, "Deleted from cache: %s : %s\n", 250 cptr->ac_host, cptr->ac_netid); 251 #endif 252 free(cptr->ac_host); 253 free(cptr->ac_netid); 254 free(cptr->ac_taddr->buf); 255 free(cptr->ac_taddr); 256 if (cptr->ac_uaddr) 257 free(cptr->ac_uaddr); 258 259 if (prevptr) { 260 prevptr->ac_next = NULL; 261 ad_cache->ac_next = front; 262 front = ad_cache; 263 } else { 264 front = ad_cache; 265 ad_cache->ac_next = NULL; 266 } 267 free(cptr); 268 } 269 rwlock_unlock(&rpcbaddr_cache_lock); 270 } 271 272 /* 273 * This routine will return a client handle that is connected to the 274 * rpcbind. If targaddr is non-NULL, the "universal address" of the 275 * host will be stored in *targaddr; the caller is responsible for 276 * freeing this string. 277 * On error, returns NULL and free's everything. 278 */ 279 static CLIENT * 280 getclnthandle(host, nconf, targaddr) 281 const char *host; 282 const struct netconfig *nconf; 283 char **targaddr; 284 { 285 CLIENT *client; 286 struct netbuf *addr, taddr; 287 struct netbuf addr_to_delete; 288 struct __rpc_sockinfo si; 289 struct addrinfo hints, *res, *tres; 290 struct address_cache *ad_cache; 291 char *tmpaddr; 292 293 /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */ 294 295 /* Get the address of the rpcbind. Check cache first */ 296 client = NULL; 297 addr_to_delete.len = 0; 298 rwlock_rdlock(&rpcbaddr_cache_lock); 299 ad_cache = NULL; 300 if (host != NULL) 301 ad_cache = check_cache(host, nconf->nc_netid); 302 if (ad_cache != NULL) { 303 addr = ad_cache->ac_taddr; 304 client = clnt_tli_create(RPC_ANYFD, nconf, addr, 305 (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 306 if (client != NULL) { 307 if (targaddr) 308 *targaddr = strdup(ad_cache->ac_uaddr); 309 rwlock_unlock(&rpcbaddr_cache_lock); 310 return (client); 311 } 312 addr_to_delete.len = addr->len; 313 addr_to_delete.buf = (char *)malloc(addr->len); 314 if (addr_to_delete.buf == NULL) { 315 addr_to_delete.len = 0; 316 } else { 317 memcpy(addr_to_delete.buf, addr->buf, addr->len); 318 } 319 } 320 rwlock_unlock(&rpcbaddr_cache_lock); 321 if (addr_to_delete.len != 0) { 322 /* 323 * Assume this may be due to cache data being 324 * outdated 325 */ 326 rwlock_wrlock(&rpcbaddr_cache_lock); 327 delete_cache(&addr_to_delete); 328 rwlock_unlock(&rpcbaddr_cache_lock); 329 free(addr_to_delete.buf); 330 } 331 if (!__rpc_nconf2sockinfo(nconf, &si)) { 332 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 333 return NULL; 334 } 335 336 memset(&hints, 0, sizeof hints); 337 hints.ai_family = si.si_af; 338 hints.ai_socktype = si.si_socktype; 339 hints.ai_protocol = si.si_proto; 340 341 #ifdef CLNT_DEBUG 342 printf("trying netid %s family %d proto %d socktype %d\n", 343 nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); 344 #endif 345 346 if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 347 client = local_rpcb(); 348 if (! client) { 349 #ifdef ND_DEBUG 350 clnt_pcreateerror("rpcbind clnt interface"); 351 #endif 352 return (NULL); 353 } else { 354 struct sockaddr_un sun; 355 if (targaddr) { 356 *targaddr = malloc(sizeof(sun.sun_path)); 357 if (*targaddr == NULL) { 358 CLNT_DESTROY(client); 359 return (NULL); 360 } 361 strncpy(*targaddr, _PATH_RPCBINDSOCK, 362 sizeof(sun.sun_path)); 363 } 364 return (client); 365 } 366 } else { 367 if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { 368 rpc_createerr.cf_stat = RPC_UNKNOWNHOST; 369 return NULL; 370 } 371 } 372 373 for (tres = res; tres != NULL; tres = tres->ai_next) { 374 taddr.buf = tres->ai_addr; 375 taddr.len = taddr.maxlen = tres->ai_addrlen; 376 377 #ifdef ND_DEBUG 378 { 379 char *ua; 380 381 ua = taddr2uaddr(nconf, &taddr); 382 fprintf(stderr, "Got it [%s]\n", ua); 383 free(ua); 384 } 385 #endif 386 387 #ifdef ND_DEBUG 388 { 389 int i; 390 391 fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", 392 taddr.len, taddr.maxlen); 393 fprintf(stderr, "\tAddress is "); 394 for (i = 0; i < taddr.len; i++) 395 fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); 396 fprintf(stderr, "\n"); 397 } 398 #endif 399 client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, 400 (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); 401 #ifdef ND_DEBUG 402 if (! client) { 403 clnt_pcreateerror("rpcbind clnt interface"); 404 } 405 #endif 406 407 if (client) { 408 tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; 409 add_cache(host, nconf->nc_netid, &taddr, tmpaddr); 410 if (targaddr) 411 *targaddr = tmpaddr; 412 break; 413 } 414 } 415 if (res) 416 freeaddrinfo(res); 417 return (client); 418 } 419 420 #endif 421 422 /* XXX */ 423 #define IN4_LOCALHOST_STRING "127.0.0.1" 424 #define IN6_LOCALHOST_STRING "::1" 425 426 /* 427 * This routine will return a client handle that is connected to the local 428 * rpcbind. Returns NULL on error and free's everything. 429 */ 430 static CLIENT * 431 local_rpcb(void) 432 { 433 CLIENT *client; 434 struct socket *so; 435 size_t tsize; 436 struct sockaddr_un sun; 437 int error; 438 439 /* 440 * Try connecting to the local rpcbind through a local socket 441 * first. If this doesn't work, try all transports defined in 442 * the netconfig file. 443 */ 444 memset(&sun, 0, sizeof sun); 445 so = NULL; 446 error = socreate(AF_LOCAL, &so, SOCK_STREAM, 0, curthread->td_ucred, 447 curthread); 448 if (error) 449 goto try_nconf; 450 sun.sun_family = AF_LOCAL; 451 strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 452 sun.sun_len = SUN_LEN(&sun); 453 454 tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); 455 client = clnt_vc_create(so, (struct sockaddr *)&sun, (rpcprog_t)RPCBPROG, 456 (rpcvers_t)RPCBVERS, tsize, tsize, 1); 457 458 if (client != NULL) { 459 /* Mark the socket to be closed in destructor */ 460 (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); 461 return client; 462 } 463 464 /* Nobody needs this socket anymore; free the descriptor. */ 465 soclose(so); 466 467 try_nconf: 468 469 #if 0 470 static struct netconfig *loopnconf; 471 static char *localhostname; 472 473 /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ 474 mutex_lock(&loopnconf_lock); 475 if (loopnconf == NULL) { 476 struct netconfig *nconf, *tmpnconf = NULL; 477 void *nc_handle; 478 int fd; 479 480 nc_handle = setnetconfig(); 481 if (nc_handle == NULL) { 482 /* fails to open netconfig file */ 483 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 484 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 485 mutex_unlock(&loopnconf_lock); 486 return (NULL); 487 } 488 while ((nconf = getnetconfig(nc_handle)) != NULL) { 489 if (( 490 #ifdef INET6 491 strcmp(nconf->nc_protofmly, NC_INET6) == 0 || 492 #endif 493 strcmp(nconf->nc_protofmly, NC_INET) == 0) && 494 (nconf->nc_semantics == NC_TPI_COTS || 495 nconf->nc_semantics == NC_TPI_COTS_ORD)) { 496 fd = __rpc_nconf2fd(nconf); 497 /* 498 * Can't create a socket, assume that 499 * this family isn't configured in the kernel. 500 */ 501 if (fd < 0) 502 continue; 503 _close(fd); 504 tmpnconf = nconf; 505 if (!strcmp(nconf->nc_protofmly, NC_INET)) 506 localhostname = IN4_LOCALHOST_STRING; 507 else 508 localhostname = IN6_LOCALHOST_STRING; 509 } 510 } 511 if (tmpnconf == NULL) { 512 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 513 mutex_unlock(&loopnconf_lock); 514 return (NULL); 515 } 516 loopnconf = getnetconfigent(tmpnconf->nc_netid); 517 /* loopnconf is never freed */ 518 endnetconfig(nc_handle); 519 } 520 mutex_unlock(&loopnconf_lock); 521 client = getclnthandle(localhostname, loopnconf, NULL); 522 return (client); 523 #else 524 return (NULL); 525 #endif 526 } 527 528 /* 529 * Set a mapping between program, version and address. 530 * Calls the rpcbind service to do the mapping. 531 */ 532 bool_t 533 rpcb_set(rpcprog_t program, rpcvers_t version, 534 const struct netconfig *nconf, /* Network structure of transport */ 535 const struct netbuf *address) /* Services netconfig address */ 536 { 537 CLIENT *client; 538 bool_t rslt = FALSE; 539 RPCB parms; 540 #if 0 541 char uidbuf[32]; 542 #endif 543 struct netconfig nconfcopy; 544 struct netbuf addresscopy; 545 546 /* parameter checking */ 547 if (nconf == NULL) { 548 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 549 return (FALSE); 550 } 551 if (address == NULL) { 552 rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 553 return (FALSE); 554 } 555 client = local_rpcb(); 556 if (! client) { 557 return (FALSE); 558 } 559 560 /* convert to universal */ 561 /*LINTED const castaway*/ 562 nconfcopy = *nconf; 563 addresscopy = *address; 564 parms.r_addr = taddr2uaddr(&nconfcopy, &addresscopy); 565 if (!parms.r_addr) { 566 CLNT_DESTROY(client); 567 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 568 return (FALSE); /* no universal address */ 569 } 570 parms.r_prog = program; 571 parms.r_vers = version; 572 parms.r_netid = nconf->nc_netid; 573 #if 0 574 /* 575 * Though uid is not being used directly, we still send it for 576 * completeness. For non-unix platforms, perhaps some other 577 * string or an empty string can be sent. 578 */ 579 (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 580 parms.r_owner = uidbuf; 581 #else 582 parms.r_owner = ""; 583 #endif 584 585 CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb, 586 (char *)(void *)&parms, (xdrproc_t) xdr_bool, 587 (char *)(void *)&rslt, tottimeout); 588 589 CLNT_DESTROY(client); 590 free(parms.r_addr, M_RPC); 591 return (rslt); 592 } 593 594 /* 595 * Remove the mapping between program, version and netbuf address. 596 * Calls the rpcbind service to do the un-mapping. 597 * If netbuf is NULL, unset for all the transports, otherwise unset 598 * only for the given transport. 599 */ 600 bool_t 601 rpcb_unset(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf) 602 { 603 CLIENT *client; 604 bool_t rslt = FALSE; 605 RPCB parms; 606 #if 0 607 char uidbuf[32]; 608 #endif 609 610 client = local_rpcb(); 611 if (! client) { 612 return (FALSE); 613 } 614 615 parms.r_prog = program; 616 parms.r_vers = version; 617 if (nconf) 618 parms.r_netid = nconf->nc_netid; 619 else { 620 /*LINTED const castaway*/ 621 parms.r_netid = (char *)(uintptr_t) &nullstring[0]; /* unsets all */ 622 } 623 /*LINTED const castaway*/ 624 parms.r_addr = (char *)(uintptr_t) &nullstring[0]; 625 #if 0 626 (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid()); 627 parms.r_owner = uidbuf; 628 #else 629 parms.r_owner = ""; 630 #endif 631 632 CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, 633 (char *)(void *)&parms, (xdrproc_t) xdr_bool, 634 (char *)(void *)&rslt, tottimeout); 635 636 CLNT_DESTROY(client); 637 return (rslt); 638 } 639 640 #if 0 641 642 /* 643 * From the merged list, find the appropriate entry 644 */ 645 static struct netbuf * 646 got_entry(relp, nconf) 647 rpcb_entry_list_ptr relp; 648 const struct netconfig *nconf; 649 { 650 struct netbuf *na = NULL; 651 rpcb_entry_list_ptr sp; 652 rpcb_entry *rmap; 653 654 for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { 655 rmap = &sp->rpcb_entry_map; 656 if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && 657 (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && 658 (nconf->nc_semantics == rmap->r_nc_semantics) && 659 (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) { 660 na = uaddr2taddr(nconf, rmap->r_maddr); 661 #ifdef ND_DEBUG 662 fprintf(stderr, "\tRemote address is [%s].\n", 663 rmap->r_maddr); 664 if (!na) 665 fprintf(stderr, 666 "\tCouldn't resolve remote address!\n"); 667 #endif 668 break; 669 } 670 } 671 return (na); 672 } 673 674 /* 675 * Quick check to see if rpcbind is up. Tries to connect over 676 * local transport. 677 */ 678 static bool_t 679 __rpcbind_is_up() 680 { 681 struct netconfig *nconf; 682 struct sockaddr_un sun; 683 void *localhandle; 684 int sock; 685 686 nconf = NULL; 687 localhandle = setnetconfig(); 688 while ((nconf = getnetconfig(localhandle)) != NULL) { 689 if (nconf->nc_protofmly != NULL && 690 strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) 691 break; 692 } 693 if (nconf == NULL) 694 return (FALSE); 695 696 endnetconfig(localhandle); 697 698 memset(&sun, 0, sizeof sun); 699 sock = _socket(AF_LOCAL, SOCK_STREAM, 0); 700 if (sock < 0) 701 return (FALSE); 702 sun.sun_family = AF_LOCAL; 703 strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); 704 sun.sun_len = SUN_LEN(&sun); 705 706 if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) { 707 _close(sock); 708 return (FALSE); 709 } 710 711 _close(sock); 712 return (TRUE); 713 } 714 715 /* 716 * An internal function which optimizes rpcb_getaddr function. It also 717 * returns the client handle that it uses to contact the remote rpcbind. 718 * 719 * The algorithm used: If the transports is TCP or UDP, it first tries 720 * version 2 (portmap), 4 and then 3 (svr4). This order should be 721 * changed in the next OS release to 4, 2 and 3. We are assuming that by 722 * that time, version 4 would be available on many machines on the network. 723 * With this algorithm, we get performance as well as a plan for 724 * obsoleting version 2. 725 * 726 * For all other transports, the algorithm remains as 4 and then 3. 727 * 728 * XXX: Due to some problems with t_connect(), we do not reuse the same client 729 * handle for COTS cases and hence in these cases we do not return the 730 * client handle. This code will change if t_connect() ever 731 * starts working properly. Also look under clnt_vc.c. 732 */ 733 struct netbuf * 734 __rpcb_findaddr_timed(program, version, nconf, host, clpp, tp) 735 rpcprog_t program; 736 rpcvers_t version; 737 const struct netconfig *nconf; 738 const char *host; 739 CLIENT **clpp; 740 struct timeval *tp; 741 { 742 static bool_t check_rpcbind = TRUE; 743 CLIENT *client = NULL; 744 RPCB parms; 745 enum clnt_stat clnt_st; 746 char *ua = NULL; 747 rpcvers_t vers; 748 struct netbuf *address = NULL; 749 rpcvers_t start_vers = RPCBVERS4; 750 struct netbuf servaddr; 751 752 /* parameter checking */ 753 if (nconf == NULL) { 754 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 755 return (NULL); 756 } 757 758 parms.r_addr = NULL; 759 760 /* 761 * Use default total timeout if no timeout is specified. 762 */ 763 if (tp == NULL) 764 tp = &tottimeout; 765 766 #ifdef PORTMAP 767 /* Try version 2 for TCP or UDP */ 768 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 769 u_short port = 0; 770 struct netbuf remote; 771 rpcvers_t pmapvers = 2; 772 struct pmap pmapparms; 773 774 /* 775 * Try UDP only - there are some portmappers out 776 * there that use UDP only. 777 */ 778 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 779 struct netconfig *newnconf; 780 781 if ((newnconf = getnetconfigent("udp")) == NULL) { 782 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 783 return (NULL); 784 } 785 client = getclnthandle(host, newnconf, &parms.r_addr); 786 freenetconfigent(newnconf); 787 } else { 788 client = getclnthandle(host, nconf, &parms.r_addr); 789 } 790 if (client == NULL) 791 return (NULL); 792 793 /* 794 * Set version and retry timeout. 795 */ 796 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 797 CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers); 798 799 pmapparms.pm_prog = program; 800 pmapparms.pm_vers = version; 801 pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? 802 IPPROTO_UDP : IPPROTO_TCP; 803 pmapparms.pm_port = 0; /* not needed */ 804 clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, 805 (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms, 806 (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port, 807 *tp); 808 if (clnt_st != RPC_SUCCESS) { 809 if ((clnt_st == RPC_PROGVERSMISMATCH) || 810 (clnt_st == RPC_PROGUNAVAIL)) 811 goto try_rpcbind; /* Try different versions */ 812 rpc_createerr.cf_stat = RPC_PMAPFAILURE; 813 clnt_geterr(client, &rpc_createerr.cf_error); 814 goto error; 815 } else if (port == 0) { 816 address = NULL; 817 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 818 goto error; 819 } 820 port = htons(port); 821 CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote); 822 if (((address = (struct netbuf *) 823 malloc(sizeof (struct netbuf))) == NULL) || 824 ((address->buf = (char *) 825 malloc(remote.len)) == NULL)) { 826 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 827 clnt_geterr(client, &rpc_createerr.cf_error); 828 if (address) { 829 free(address); 830 address = NULL; 831 } 832 goto error; 833 } 834 memcpy(address->buf, remote.buf, remote.len); 835 memcpy(&((char *)address->buf)[sizeof (short)], 836 (char *)(void *)&port, sizeof (short)); 837 address->len = address->maxlen = remote.len; 838 goto done; 839 } 840 #endif /* PORTMAP */ 841 842 try_rpcbind: 843 /* 844 * Check if rpcbind is up. This prevents needless delays when 845 * accessing applications such as the keyserver while booting 846 * disklessly. 847 */ 848 if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 849 if (!__rpcbind_is_up()) { 850 rpc_createerr.cf_stat = RPC_PMAPFAILURE; 851 rpc_createerr.cf_error.re_errno = 0; 852 goto error; 853 } 854 check_rpcbind = FALSE; 855 } 856 857 /* 858 * Now we try version 4 and then 3. 859 * We also send the remote system the address we used to 860 * contact it in case it can help to connect back with us 861 */ 862 parms.r_prog = program; 863 parms.r_vers = version; 864 /*LINTED const castaway*/ 865 parms.r_owner = (char *) &nullstring[0]; /* not needed; */ 866 /* just for xdring */ 867 parms.r_netid = nconf->nc_netid; /* not really needed */ 868 869 /* 870 * If a COTS transport is being used, try getting address via CLTS 871 * transport. This works only with version 4. 872 */ 873 if (nconf->nc_semantics == NC_TPI_COTS_ORD || 874 nconf->nc_semantics == NC_TPI_COTS) { 875 876 void *handle; 877 struct netconfig *nconf_clts; 878 rpcb_entry_list_ptr relp = NULL; 879 880 if (client == NULL) { 881 /* This did not go through the above PORTMAP/TCP code */ 882 if ((handle = __rpc_setconf("datagram_v")) != NULL) { 883 while ((nconf_clts = __rpc_getconf(handle)) 884 != NULL) { 885 if (strcmp(nconf_clts->nc_protofmly, 886 nconf->nc_protofmly) != 0) { 887 continue; 888 } 889 client = getclnthandle(host, nconf_clts, 890 &parms.r_addr); 891 break; 892 } 893 __rpc_endconf(handle); 894 } 895 if (client == NULL) 896 goto regular_rpcbind; /* Go the regular way */ 897 } else { 898 /* This is a UDP PORTMAP handle. Change to version 4 */ 899 vers = RPCBVERS4; 900 CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 901 } 902 /* 903 * We also send the remote system the address we used to 904 * contact it in case it can help it connect back with us 905 */ 906 if (parms.r_addr == NULL) { 907 /*LINTED const castaway*/ 908 parms.r_addr = (char *) &nullstring[0]; /* for XDRing */ 909 } 910 911 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); 912 913 clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST, 914 (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 915 (xdrproc_t) xdr_rpcb_entry_list_ptr, 916 (char *)(void *)&relp, *tp); 917 if (clnt_st == RPC_SUCCESS) { 918 if ((address = got_entry(relp, nconf)) != NULL) { 919 xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 920 (char *)(void *)&relp); 921 CLNT_CONTROL(client, CLGET_SVC_ADDR, 922 (char *)(void *)&servaddr); 923 __rpc_fixup_addr(address, &servaddr); 924 goto done; 925 } 926 /* Entry not found for this transport */ 927 xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr, 928 (char *)(void *)&relp); 929 /* 930 * XXX: should have perhaps returned with error but 931 * since the remote machine might not always be able 932 * to send the address on all transports, we try the 933 * regular way with regular_rpcbind 934 */ 935 goto regular_rpcbind; 936 } else if ((clnt_st == RPC_PROGVERSMISMATCH) || 937 (clnt_st == RPC_PROGUNAVAIL)) { 938 start_vers = RPCBVERS; /* Try version 3 now */ 939 goto regular_rpcbind; /* Try different versions */ 940 } else { 941 rpc_createerr.cf_stat = RPC_PMAPFAILURE; 942 clnt_geterr(client, &rpc_createerr.cf_error); 943 goto error; 944 } 945 } 946 947 regular_rpcbind: 948 949 /* Now the same transport is to be used to get the address */ 950 if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || 951 (nconf->nc_semantics == NC_TPI_COTS))) { 952 /* A CLTS type of client - destroy it */ 953 CLNT_DESTROY(client); 954 client = NULL; 955 } 956 957 if (client == NULL) { 958 client = getclnthandle(host, nconf, &parms.r_addr); 959 if (client == NULL) { 960 goto error; 961 } 962 } 963 if (parms.r_addr == NULL) { 964 /*LINTED const castaway*/ 965 parms.r_addr = (char *) &nullstring[0]; 966 } 967 968 /* First try from start_vers and then version 3 (RPCBVERS) */ 969 970 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime); 971 for (vers = start_vers; vers >= RPCBVERS; vers--) { 972 /* Set the version */ 973 CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 974 clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR, 975 (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, 976 (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp); 977 if (clnt_st == RPC_SUCCESS) { 978 if ((ua == NULL) || (ua[0] == 0)) { 979 /* address unknown */ 980 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 981 goto error; 982 } 983 address = uaddr2taddr(nconf, ua); 984 #ifdef ND_DEBUG 985 fprintf(stderr, "\tRemote address is [%s]\n", ua); 986 if (!address) 987 fprintf(stderr, 988 "\tCouldn't resolve remote address!\n"); 989 #endif 990 xdr_free((xdrproc_t)xdr_wrapstring, 991 (char *)(void *)&ua); 992 993 if (! address) { 994 /* We don't know about your universal address */ 995 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; 996 goto error; 997 } 998 CLNT_CONTROL(client, CLGET_SVC_ADDR, 999 (char *)(void *)&servaddr); 1000 __rpc_fixup_addr(address, &servaddr); 1001 goto done; 1002 } else if (clnt_st == RPC_PROGVERSMISMATCH) { 1003 struct rpc_err rpcerr; 1004 1005 clnt_geterr(client, &rpcerr); 1006 if (rpcerr.re_vers.low > RPCBVERS4) 1007 goto error; /* a new version, can't handle */ 1008 } else if (clnt_st != RPC_PROGUNAVAIL) { 1009 /* Cant handle this error */ 1010 rpc_createerr.cf_stat = clnt_st; 1011 clnt_geterr(client, &rpc_createerr.cf_error); 1012 goto error; 1013 } 1014 } 1015 1016 error: 1017 if (client) { 1018 CLNT_DESTROY(client); 1019 client = NULL; 1020 } 1021 done: 1022 if (nconf->nc_semantics != NC_TPI_CLTS) { 1023 /* This client is the connectionless one */ 1024 if (client) { 1025 CLNT_DESTROY(client); 1026 client = NULL; 1027 } 1028 } 1029 if (clpp) { 1030 *clpp = client; 1031 } else if (client) { 1032 CLNT_DESTROY(client); 1033 } 1034 if (parms.r_addr != NULL && parms.r_addr != nullstring) 1035 free(parms.r_addr); 1036 return (address); 1037 } 1038 1039 1040 /* 1041 * Find the mapped address for program, version. 1042 * Calls the rpcbind service remotely to do the lookup. 1043 * Uses the transport specified in nconf. 1044 * Returns FALSE (0) if no map exists, else returns 1. 1045 * 1046 * Assuming that the address is all properly allocated 1047 */ 1048 bool_t 1049 rpcb_getaddr(program, version, nconf, address, host) 1050 rpcprog_t program; 1051 rpcvers_t version; 1052 const struct netconfig *nconf; 1053 struct netbuf *address; 1054 const char *host; 1055 { 1056 struct netbuf *na; 1057 1058 if ((na = __rpcb_findaddr_timed(program, version, 1059 (struct netconfig *) nconf, (char *) host, 1060 (CLIENT **) NULL, (struct timeval *) NULL)) == NULL) 1061 return (FALSE); 1062 1063 if (na->len > address->maxlen) { 1064 /* Too long address */ 1065 free(na->buf); 1066 free(na); 1067 rpc_createerr.cf_stat = RPC_FAILED; 1068 return (FALSE); 1069 } 1070 memcpy(address->buf, na->buf, (size_t)na->len); 1071 address->len = na->len; 1072 free(na->buf); 1073 free(na); 1074 return (TRUE); 1075 } 1076 1077 /* 1078 * Get a copy of the current maps. 1079 * Calls the rpcbind service remotely to get the maps. 1080 * 1081 * It returns only a list of the services 1082 * It returns NULL on failure. 1083 */ 1084 rpcblist * 1085 rpcb_getmaps(nconf, host) 1086 const struct netconfig *nconf; 1087 const char *host; 1088 { 1089 rpcblist_ptr head = NULL; 1090 CLIENT *client; 1091 enum clnt_stat clnt_st; 1092 rpcvers_t vers = 0; 1093 1094 client = getclnthandle(host, nconf, NULL); 1095 if (client == NULL) { 1096 return (head); 1097 } 1098 clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 1099 (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 1100 (char *)(void *)&head, tottimeout); 1101 if (clnt_st == RPC_SUCCESS) 1102 goto done; 1103 1104 if ((clnt_st != RPC_PROGVERSMISMATCH) && 1105 (clnt_st != RPC_PROGUNAVAIL)) { 1106 rpc_createerr.cf_stat = RPC_RPCBFAILURE; 1107 clnt_geterr(client, &rpc_createerr.cf_error); 1108 goto done; 1109 } 1110 1111 /* fall back to earlier version */ 1112 CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 1113 if (vers == RPCBVERS4) { 1114 vers = RPCBVERS; 1115 CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 1116 if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP, 1117 (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, 1118 (char *)(void *)&head, tottimeout) == RPC_SUCCESS) 1119 goto done; 1120 } 1121 rpc_createerr.cf_stat = RPC_RPCBFAILURE; 1122 clnt_geterr(client, &rpc_createerr.cf_error); 1123 1124 done: 1125 CLNT_DESTROY(client); 1126 return (head); 1127 } 1128 1129 /* 1130 * rpcbinder remote-call-service interface. 1131 * This routine is used to call the rpcbind remote call service 1132 * which will look up a service program in the address maps, and then 1133 * remotely call that routine with the given parameters. This allows 1134 * programs to do a lookup and call in one step. 1135 */ 1136 enum clnt_stat 1137 rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp, 1138 xdrres, resp, tout, addr_ptr) 1139 const struct netconfig *nconf; /* Netconfig structure */ 1140 const char *host; /* Remote host name */ 1141 rpcprog_t prog; 1142 rpcvers_t vers; 1143 rpcproc_t proc; /* Remote proc identifiers */ 1144 xdrproc_t xdrargs, xdrres; /* XDR routines */ 1145 caddr_t argsp, resp; /* Argument and Result */ 1146 struct timeval tout; /* Timeout value for this call */ 1147 const struct netbuf *addr_ptr; /* Preallocated netbuf address */ 1148 { 1149 CLIENT *client; 1150 enum clnt_stat stat; 1151 struct r_rpcb_rmtcallargs a; 1152 struct r_rpcb_rmtcallres r; 1153 rpcvers_t rpcb_vers; 1154 1155 stat = 0; 1156 client = getclnthandle(host, nconf, NULL); 1157 if (client == NULL) { 1158 return (RPC_FAILED); 1159 } 1160 /*LINTED const castaway*/ 1161 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); 1162 a.prog = prog; 1163 a.vers = vers; 1164 a.proc = proc; 1165 a.args.args_val = argsp; 1166 a.xdr_args = xdrargs; 1167 r.addr = NULL; 1168 r.results.results_val = resp; 1169 r.xdr_res = xdrres; 1170 1171 for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { 1172 CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); 1173 stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT, 1174 (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, 1175 (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); 1176 if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { 1177 struct netbuf *na; 1178 /*LINTED const castaway*/ 1179 na = uaddr2taddr((struct netconfig *) nconf, r.addr); 1180 if (!na) { 1181 stat = RPC_N2AXLATEFAILURE; 1182 /*LINTED const castaway*/ 1183 ((struct netbuf *) addr_ptr)->len = 0; 1184 goto error; 1185 } 1186 if (na->len > addr_ptr->maxlen) { 1187 /* Too long address */ 1188 stat = RPC_FAILED; /* XXX A better error no */ 1189 free(na->buf); 1190 free(na); 1191 /*LINTED const castaway*/ 1192 ((struct netbuf *) addr_ptr)->len = 0; 1193 goto error; 1194 } 1195 memcpy(addr_ptr->buf, na->buf, (size_t)na->len); 1196 /*LINTED const castaway*/ 1197 ((struct netbuf *)addr_ptr)->len = na->len; 1198 free(na->buf); 1199 free(na); 1200 break; 1201 } else if ((stat != RPC_PROGVERSMISMATCH) && 1202 (stat != RPC_PROGUNAVAIL)) { 1203 goto error; 1204 } 1205 } 1206 error: 1207 CLNT_DESTROY(client); 1208 if (r.addr) 1209 xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); 1210 return (stat); 1211 } 1212 1213 /* 1214 * Gets the time on the remote host. 1215 * Returns 1 if succeeds else 0. 1216 */ 1217 bool_t 1218 rpcb_gettime(host, timep) 1219 const char *host; 1220 time_t *timep; 1221 { 1222 CLIENT *client = NULL; 1223 void *handle; 1224 struct netconfig *nconf; 1225 rpcvers_t vers; 1226 enum clnt_stat st; 1227 1228 1229 if ((host == NULL) || (host[0] == 0)) { 1230 time(timep); 1231 return (TRUE); 1232 } 1233 1234 if ((handle = __rpc_setconf("netpath")) == NULL) { 1235 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 1236 return (FALSE); 1237 } 1238 rpc_createerr.cf_stat = RPC_SUCCESS; 1239 while (client == NULL) { 1240 if ((nconf = __rpc_getconf(handle)) == NULL) { 1241 if (rpc_createerr.cf_stat == RPC_SUCCESS) 1242 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 1243 break; 1244 } 1245 client = getclnthandle(host, nconf, NULL); 1246 if (client) 1247 break; 1248 } 1249 __rpc_endconf(handle); 1250 if (client == (CLIENT *) NULL) { 1251 return (FALSE); 1252 } 1253 1254 st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 1255 (xdrproc_t) xdr_void, NULL, 1256 (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); 1257 1258 if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { 1259 CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); 1260 if (vers == RPCBVERS4) { 1261 /* fall back to earlier version */ 1262 vers = RPCBVERS; 1263 CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); 1264 st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME, 1265 (xdrproc_t) xdr_void, NULL, 1266 (xdrproc_t) xdr_int, (char *)(void *)timep, 1267 tottimeout); 1268 } 1269 } 1270 CLNT_DESTROY(client); 1271 return (st == RPC_SUCCESS? TRUE: FALSE); 1272 } 1273 1274 static bool_t 1275 xdr_netbuf(XDR *xdrs, struct netbuf *objp) 1276 { 1277 bool_t dummy; 1278 void **pp; 1279 1280 if (!xdr_uint32_t(xdrs, (uint32_t *) &objp->maxlen)) { 1281 return (FALSE); 1282 } 1283 pp = &objp->buf; 1284 1285 if (objp->maxlen > RPC_MAXDATASIZE) { 1286 return (FALSE); 1287 } 1288 1289 dummy = xdr_bytes(xdrs, (char **) pp, 1290 (u_int *)&(objp->len), objp->maxlen); 1291 return (dummy); 1292 } 1293 1294 /* 1295 * Converts taddr to universal address. This routine should never 1296 * really be called because local n2a libraries are always provided. 1297 */ 1298 char * 1299 rpcb_taddr2uaddr(struct netconfig *nconf, struct netbuf *taddr) 1300 { 1301 CLIENT *client; 1302 char *uaddr = NULL; 1303 1304 1305 /* parameter checking */ 1306 if (nconf == NULL) { 1307 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 1308 return (NULL); 1309 } 1310 if (taddr == NULL) { 1311 rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 1312 return (NULL); 1313 } 1314 client = local_rpcb(); 1315 if (! client) { 1316 return (NULL); 1317 } 1318 1319 CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR, 1320 (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 1321 (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); 1322 CLNT_DESTROY(client); 1323 return (uaddr); 1324 } 1325 1326 /* 1327 * Converts universal address to netbuf. This routine should never 1328 * really be called because local n2a libraries are always provided. 1329 */ 1330 struct netbuf * 1331 rpcb_uaddr2taddr(struct netconfig *nconf, char *uaddr) 1332 { 1333 CLIENT *client; 1334 struct netbuf *taddr; 1335 1336 1337 /* parameter checking */ 1338 if (nconf == NULL) { 1339 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 1340 return (NULL); 1341 } 1342 if (uaddr == NULL) { 1343 rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 1344 return (NULL); 1345 } 1346 client = local_rpcb(); 1347 if (! client) { 1348 return (NULL); 1349 } 1350 1351 taddr = (struct netbuf *)malloc(sizeof (struct netbuf), M_RPC, M_WAITOK|M_ZERO); 1352 if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR, 1353 (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, 1354 (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, 1355 tottimeout) != RPC_SUCCESS) { 1356 free(taddr); 1357 taddr = NULL; 1358 } 1359 CLNT_DESTROY(client); 1360 return (taddr); 1361 } 1362 1363 #endif 1364