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