Print this page
4729 __rpcb_findaddr_timed should try rpcbind protocol 4 first
Reviewed by: Marcel Telka <marcel@telka.sk>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libnsl/rpc/rpcb_clnt.c
          +++ new/usr/src/lib/libnsl/rpc/rpcb_clnt.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * When distributing Covered Code, include this CDDL HEADER in each
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  
  23   23  /*
       24 + * Copyright 2014 Gary Mills
  24   25   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  25   26   * Use is subject to license terms.
  26   27   */
  27   28  
  28   29  /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  29   30  /* All Rights Reserved */
  30   31  /*
  31   32   * Portions of this source code were derived from Berkeley
  32   33   * 4.3 BSD under license from the Regents of the University of
  33   34   * California.
  34   35   */
  35   36  
  36      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  37      -
  38   37  /*
  39   38   * interface to rpcbind rpc service.
  40   39   */
  41   40  
  42   41  #include "mt.h"
  43   42  #include "rpc_mt.h"
  44   43  #include <assert.h>
  45   44  #include <rpc/rpc.h>
  46   45  #include <rpc/rpcb_prot.h>
  47   46  #include <netconfig.h>
  48   47  #include <netdir.h>
       48 +#include <netdb.h>
  49   49  #include <rpc/nettype.h>
  50   50  #include <syslog.h>
  51   51  #ifdef PORTMAP
  52   52  #include <netinet/in.h>         /* FOR IPPROTO_TCP/UDP definitions */
  53   53  #include <rpc/pmap_prot.h>
  54   54  #endif
  55      -#ifdef ND_DEBUG
  56      -#include <stdio.h>
  57      -#endif
  58   55  #include <sys/utsname.h>
  59   56  #include <errno.h>
  60   57  #include <stdlib.h>
  61   58  #include <string.h>
  62   59  #include <unistd.h>
  63   60  
  64   61  static struct timeval tottimeout = { 60, 0 };
  65   62  static const struct timeval rmttimeout = { 3, 0 };
  66   63  static struct timeval rpcbrmttime = { 15, 0 };
  67   64  
↓ open down ↓ 94 lines elided ↑ open up ↑
 162  159  check_cache(char *host, char *netid)
 163  160  {
 164  161          struct address_cache *cptr;
 165  162  
 166  163          /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
 167  164  
 168  165          assert(RW_READ_HELD(&rpcbaddr_cache_lock));
 169  166          for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
 170  167                  if ((strcmp(cptr->ac_host, host) == 0) &&
 171  168                      (strcmp(cptr->ac_netid, netid) == 0) &&
 172      -                        (time(NULL) <= cptr->ac_maxtime)) {
 173      -#ifdef ND_DEBUG
 174      -                        fprintf(stderr, "Found cache entry for %s: %s\n",
 175      -                                host, netid);
 176      -#endif
      169 +                    (time(NULL) <= cptr->ac_maxtime)) {
 177  170                          return (cptr);
 178  171                  }
 179  172          }
 180  173          return (NULL);
 181  174  }
 182  175  
 183  176  static void
 184  177  delete_cache(struct netbuf *addr)
 185  178  {
 186  179          struct address_cache *cptr, *prevptr = NULL;
↓ open down ↓ 28 lines elided ↑ open up ↑
 215  208          ad_cache = malloc(sizeof (struct address_cache));
 216  209          if (!ad_cache) {
 217  210                  goto memerr;
 218  211          }
 219  212          ad_cache->ac_maxtime = time(NULL) + CACHE_TTL;
 220  213          ad_cache->ac_host = strdup(host);
 221  214          ad_cache->ac_netid = strdup(netid);
 222  215          ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
 223  216          ad_cache->ac_taddr = malloc(sizeof (struct netbuf));
 224  217          if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
 225      -                (uaddr && !ad_cache->ac_uaddr)) {
      218 +            (uaddr && !ad_cache->ac_uaddr)) {
 226  219                  goto memerr1;
 227  220          }
 228  221  
 229  222          ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
 230  223          ad_cache->ac_taddr->buf = malloc(taddr->len);
 231  224          if (ad_cache->ac_taddr->buf == NULL) {
 232  225                  goto memerr1;
 233  226          }
 234  227  
 235  228          (void) memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
 236      -#ifdef ND_DEBUG
 237      -        (void) fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
 238      -#endif
 239  229  
 240  230  /* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  cptr */
 241  231  
 242  232          (void) rw_wrlock(&rpcbaddr_cache_lock);
 243  233          if (cachesize < CACHESIZE) {
 244  234                  ad_cache->ac_next = front;
 245  235                  front = ad_cache;
 246  236                  cachesize++;
 247  237          } else {
 248  238                  /* Free the last entry */
 249  239                  cptr = front;
 250  240                  prevptr = NULL;
 251  241                  while (cptr->ac_next) {
 252  242                          prevptr = cptr;
 253  243                          cptr = cptr->ac_next;
 254  244                  }
 255  245  
 256      -#ifdef ND_DEBUG
 257      -                fprintf(stderr, "Deleted from cache: %s : %s\n",
 258      -                        cptr->ac_host, cptr->ac_netid);
 259      -#endif
 260  246                  free(cptr->ac_host);
 261  247                  free(cptr->ac_netid);
 262  248                  free(cptr->ac_taddr->buf);
 263  249                  free(cptr->ac_taddr);
 264  250                  if (cptr->ac_uaddr)
 265  251                          free(cptr->ac_uaddr);
 266  252  
 267  253                  if (prevptr) {
 268  254                          prevptr->ac_next = NULL;
 269  255                          ad_cache->ac_next = front;
↓ open down ↓ 52 lines elided ↑ open up ↑
 322  308  
 323  309  /* VARIABLES PROTECTED BY rpcbaddr_cache_lock:  ad_cache */
 324  310  
 325  311          /* Get the address of the rpcbind.  Check cache first */
 326  312          addr_to_delete.len = 0;
 327  313          (void) rw_rdlock(&rpcbaddr_cache_lock);
 328  314          ad_cache = check_cache(host, nconf->nc_netid);
 329  315          if (ad_cache != NULL) {
 330  316                  addr = ad_cache->ac_taddr;
 331  317                  client = _clnt_tli_create_timed(RPC_ANYFD, nconf, addr,
 332      -                                RPCBPROG, RPCBVERS4, 0, 0, tp);
      318 +                    RPCBPROG, RPCBVERS4, 0, 0, tp);
 333  319                  if (client != NULL) {
 334  320                          if (targaddr) {
 335  321                                  /*
 336  322                                   * case where a client handle is created
 337  323                                   * without a targaddr and the handle is
 338  324                                   * requested with a targaddr
 339  325                                   */
 340  326                                  if (ad_cache->ac_uaddr != NULL) {
 341  327                                          *targaddr = strdup(ad_cache->ac_uaddr);
 342  328                                          if (*targaddr == NULL) {
 343  329                                                  syslog(LOG_ERR,
 344  330                                                  "_getclnthandle_timed: strdup "
 345  331                                                  "failed.");
 346  332                                                  rpc_createerr.cf_stat =
 347      -                                                        RPC_SYSTEMERROR;
      333 +                                                    RPC_SYSTEMERROR;
 348  334                                                  (void) rw_unlock(
 349      -                                                        &rpcbaddr_cache_lock);
      335 +                                                    &rpcbaddr_cache_lock);
 350  336                                                  return (NULL);
 351  337                                          }
 352  338                                  } else {
 353  339                                          *targaddr = NULL;
 354  340                                  }
 355  341                          }
 356  342                          (void) rw_unlock(&rpcbaddr_cache_lock);
 357  343                          return (client);
 358  344                  }
 359  345                  if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) {
↓ open down ↓ 14 lines elided ↑ open up ↑
 374  360                   * Assume this may be due to cache data being
 375  361                   *  outdated
 376  362                   */
 377  363                  (void) rw_wrlock(&rpcbaddr_cache_lock);
 378  364                  delete_cache(&addr_to_delete);
 379  365                  (void) rw_unlock(&rpcbaddr_cache_lock);
 380  366                  free(addr_to_delete.buf);
 381  367          }
 382  368          rpcbind_hs.h_host = host;
 383  369          rpcbind_hs.h_serv = "rpcbind";
 384      -#ifdef ND_DEBUG
 385      -        fprintf(stderr, "rpcbind client routines: diagnostics :\n");
 386      -        fprintf(stderr, "\tGetting address for (%s, %s, %s) ... \n",
 387      -                rpcbind_hs.h_host, rpcbind_hs.h_serv, nconf->nc_netid);
 388      -#endif
 389  370  
 390  371          if ((neterr = netdir_getbyname(nconf, &rpcbind_hs, &nas)) != 0) {
 391  372                  if (neterr == ND_NOHOST)
 392  373                          rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
 393  374                  else
 394  375                          rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
 395  376                  return (NULL);
 396  377          }
 397  378          /* XXX nas should perhaps be cached for better performance */
 398  379  
 399  380          for (j = 0; j < nas->n_cnt; j++) {
 400  381                  addr = &(nas->n_addrs[j]);
 401      -#ifdef ND_DEBUG
 402      -{
 403      -        int i;
 404      -        char *ua;
 405      -
 406      -        ua = taddr2uaddr(nconf, &(nas->n_addrs[j]));
 407      -        fprintf(stderr, "Got it [%s]\n", ua);
 408      -        free(ua);
 409      -
 410      -        fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
 411      -                addr->len, addr->maxlen);
 412      -        fprintf(stderr, "\tAddress is ");
 413      -        for (i = 0; i < addr->len; i++)
 414      -                fprintf(stderr, "%u.", addr->buf[i]);
 415      -        fprintf(stderr, "\n");
 416      -}
 417      -#endif
 418  382          client = _clnt_tli_create_timed(RPC_ANYFD, nconf, addr, RPCBPROG,
 419      -                                RPCBVERS4, 0, 0, tp);
      383 +            RPCBVERS4, 0, 0, tp);
 420  384          if (client)
 421  385                  break;
 422  386          }
 423      -#ifdef ND_DEBUG
 424      -        if (!client) {
 425      -                clnt_pcreateerror("rpcbind clnt interface");
 426      -        }
 427      -#endif
 428  387  
 429  388          if (client) {
 430  389                  tmpaddr = targaddr ? taddr2uaddr(nconf, addr) : NULL;
 431  390                  add_cache(host, nconf->nc_netid, addr, tmpaddr);
 432  391                  if (targaddr) {
 433  392                          *targaddr = tmpaddr;
 434  393                  }
 435  394          }
 436  395          netdir_free((char *)nas, ND_ADDRLIST);
 437  396          return (client);
 438  397  }
 439  398  
 440  399  /*
 441  400   * This routine will return a client handle that is connected to the local
 442      - * rpcbind. Returns NULL on error and free's everything.
      401 + * rpcbind. Returns NULL on error.
 443  402   */
 444  403  static CLIENT *
 445  404  local_rpcb(void)
 446  405  {
 447  406          static struct netconfig *loopnconf;
 448      -        static char *hostname;
      407 +        static char hostname[MAXHOSTNAMELEN + 1];
 449  408          extern mutex_t loopnconf_lock;
 450  409  
 451  410  /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
 452  411          (void) mutex_lock(&loopnconf_lock);
 453  412          if (loopnconf == NULL) {
 454      -                struct utsname utsname;
 455  413                  struct netconfig *nconf, *tmpnconf = NULL;
 456  414                  void *nc_handle;
 457  415  
 458      -                if (hostname == NULL) {
 459      -#if defined(__i386) && !defined(__amd64)
 460      -                        if ((_nuname(&utsname) == -1) ||
 461      -#else
 462      -                        if ((uname(&utsname) == -1) ||
 463      -#endif
 464      -                            ((hostname = strdup(utsname.nodename)) == NULL)) {
 465      -                                syslog(LOG_ERR, "local_rpcb : strdup failed.");
 466      -                                rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
 467      -                                (void) mutex_unlock(&loopnconf_lock);
 468      -                                return (NULL);
 469      -                        }
      416 +                if ((hostname[0] == '\0') && (gethostname(hostname,
      417 +                    sizeof (hostname)) < 0)) {
      418 +                        syslog(LOG_ERR, "local_rpcb: gethostname failed.");
      419 +                        rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
      420 +                        (void) mutex_unlock(&loopnconf_lock);
      421 +                        return (NULL);
 470  422                  }
 471  423                  nc_handle = setnetconfig();
 472  424                  if (nc_handle == NULL) {
 473  425                          /* fails to open netconfig file */
 474  426                          rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
 475  427                          (void) mutex_unlock(&loopnconf_lock);
 476  428                          return (NULL);
 477  429                  }
 478  430                  while (nconf = getnetconfig(nc_handle)) {
 479  431                          if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
↓ open down ↓ 35 lines elided ↑ open up ↑
 515  467          }
 516  468          if (address == NULL) {
 517  469                  rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
 518  470                  return (FALSE);
 519  471          }
 520  472          client = local_rpcb();
 521  473          if (!client)
 522  474                  return (FALSE);
 523  475  
 524  476          parms.r_addr = taddr2uaddr((struct netconfig *)nconf,
 525      -                        (struct netbuf *)address); /* convert to universal */
      477 +            (struct netbuf *)address); /* convert to universal */
 526  478          if (!parms.r_addr) {
 527  479                  rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
 528  480                  return (FALSE); /* no universal address */
 529  481          }
 530  482          parms.r_prog = program;
 531  483          parms.r_vers = version;
 532  484          parms.r_netid = nconf->nc_netid;
 533  485          /*
 534  486           * Though uid is not being used directly, we still send it for
 535  487           * completeness.  For non-unix platforms, perhaps some other
 536  488           * string or an empty string can be sent.
 537  489           */
 538  490          (void) sprintf(uidbuf, "%d", (int)geteuid());
 539  491          parms.r_owner = uidbuf;
 540  492  
 541  493          CLNT_CALL(client, RPCBPROC_SET, (xdrproc_t)xdr_rpcb, (char *)&parms,
 542      -                        (xdrproc_t)xdr_bool, (char *)&rslt, tottimeout);
      494 +            (xdrproc_t)xdr_bool, (char *)&rslt, tottimeout);
 543  495  
 544  496          CLNT_DESTROY(client);
 545  497          free(parms.r_addr);
 546  498          return (rslt);
 547  499  }
 548  500  
 549  501  /*
 550  502   * Remove the mapping between program, version and netbuf address.
 551  503   * Calls the rpcbind service to do the un-mapping.
 552  504   * If netbuf is NULL, unset for all the transports, otherwise unset
↓ open down ↓ 16 lines elided ↑ open up ↑
 569  521          parms.r_vers = version;
 570  522          if (nconf)
 571  523                  parms.r_netid = nconf->nc_netid;
 572  524          else
 573  525                  parms.r_netid = (char *)&nullstring[0]; /* unsets  all */
 574  526          parms.r_addr = (char *)&nullstring[0];
 575  527          (void) sprintf(uidbuf, "%d", (int)geteuid());
 576  528          parms.r_owner = uidbuf;
 577  529  
 578  530          CLNT_CALL(client, RPCBPROC_UNSET, (xdrproc_t)xdr_rpcb, (char *)&parms,
 579      -                        (xdrproc_t)xdr_bool, (char *)&rslt, tottimeout);
      531 +            (xdrproc_t)xdr_bool, (char *)&rslt, tottimeout);
 580  532  
 581  533          CLNT_DESTROY(client);
 582  534          return (rslt);
 583  535  }
 584  536  
 585  537  /*
 586  538   * From the merged list, find the appropriate entry
 587  539   */
 588  540  static struct netbuf *
 589  541  got_entry(rpcb_entry_list_ptr relp, struct netconfig *nconf)
↓ open down ↓ 2 lines elided ↑ open up ↑
 592  544          rpcb_entry_list_ptr sp;
 593  545          rpcb_entry *rmap;
 594  546  
 595  547          for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
 596  548                  rmap = &sp->rpcb_entry_map;
 597  549                  if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
 598  550                      (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
 599  551                      (nconf->nc_semantics == rmap->r_nc_semantics) &&
 600  552                      (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != NULL)) {
 601  553                          na = uaddr2taddr(nconf, rmap->r_maddr);
 602      -#ifdef ND_DEBUG
 603      -                        fprintf(stderr, "\tRemote address is [%s].\n",
 604      -                                rmap->r_maddr);
 605      -                        if (!na)
 606      -                                fprintf(stderr,
 607      -                                    "\tCouldn't resolve remote address!\n");
 608      -#endif
 609  554                          break;
 610  555                  }
 611  556          }
 612  557          return (na);
 613  558  }
 614  559  
 615  560  /*
 616  561   * Quick check to see if rpcbind is up.  Tries to connect over
 617  562   * local transport.
 618  563   */
 619  564  bool_t
 620  565  __rpcbind_is_up(void)
 621  566  {
 622      -        struct utsname name;
      567 +        char hostname[MAXHOSTNAMELEN + 1];
 623  568          char uaddr[SYS_NMLN];
 624  569          struct netbuf *addr;
 625  570          int fd;
 626  571          struct t_call *sndcall;
 627  572          struct netconfig *netconf;
 628  573          bool_t res;
 629  574  
 630      -#if defined(__i386) && !defined(__amd64)
 631      -        if (_nuname(&name) == -1)
 632      -#else
 633      -        if (uname(&name) == -1)
 634      -#endif
      575 +        if (gethostname(hostname, sizeof (hostname)) < 0)
 635  576                  return (TRUE);
 636  577  
 637  578          if ((fd = t_open("/dev/ticotsord", O_RDWR, NULL)) == -1)
 638  579                  return (TRUE);
 639  580  
 640  581          if (t_bind(fd, NULL, NULL) == -1) {
 641  582                  (void) t_close(fd);
 642  583                  return (TRUE);
 643  584          }
 644  585  
 645  586          /* LINTED pointer cast */
 646  587          if ((sndcall = (struct t_call *)t_alloc(fd, T_CALL, 0)) == NULL) {
 647  588                  (void) t_close(fd);
 648  589                  return (TRUE);
 649  590          }
 650  591  
 651  592          uaddr[0] = '\0';
 652      -        (void) strcpy(uaddr, name.nodename);
      593 +        (void) strlcpy(uaddr, hostname, sizeof (uaddr) - 5);
 653  594          (void) strcat(uaddr, ".rpc");
 654  595          if ((netconf = getnetconfigent("ticotsord")) == NULL) {
 655  596                  (void) t_free((char *)sndcall, T_CALL);
 656  597                  (void) t_close(fd);
 657  598                  return (FALSE);
 658  599          }
 659  600          addr = uaddr2taddr(netconf, uaddr);
 660  601          freenetconfigent(netconf);
 661  602          if (addr == NULL || addr->buf == NULL) {
 662  603                  if (addr)
↓ open down ↓ 16 lines elided ↑ open up ↑
 679  620          (void) t_free((char *)sndcall, T_CALL);
 680  621          free(addr->buf);
 681  622          free(addr);
 682  623          (void) t_close(fd);
 683  624  
 684  625          return (res);
 685  626  }
 686  627  
 687  628  
 688  629  /*
 689      - * An internal function which optimizes rpcb_getaddr function.  It also
      630 + * An internal function which optimizes rpcb_getaddr function.  It returns
      631 + * the universal address of the remote service or NULL.  It also optionally
 690  632   * returns the client handle that it uses to contact the remote rpcbind.
      633 + * The caller will re-purpose the client handle to contact the remote service.
 691  634   *
 692      - * The algorithm used: If the transports is TCP or UDP, it first tries
 693      - * version 2 (portmap), 4 and then 3 (svr4).  This order should be
 694      - * changed in the next OS release to 4, 2 and 3.  We are assuming that by
 695      - * that time, version 4 would be available on many machines on the network.
      635 + * The algorithm used: First try version 4.  Then try version 3 (svr4).
      636 + * Finally, if the transport is TCP or UDP, try version 2 (portmap).
      637 + * Version 4 is now available with all current systems on the network.
 696  638   * With this algorithm, we get performance as well as a plan for
 697  639   * obsoleting version 2.
 698  640   *
 699      - * For all other transports, the algorithm remains as 4 and then 3.
 700      - *
 701  641   * XXX: Due to some problems with t_connect(), we do not reuse the same client
 702  642   * handle for COTS cases and hence in these cases we do not return the
 703  643   * client handle.  This code will change if t_connect() ever
 704  644   * starts working properly.  Also look under clnt_vc.c.
 705  645   */
 706  646  struct netbuf *
 707  647  __rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version,
 708  648          struct netconfig *nconf, char *host, CLIENT **clpp, struct timeval *tp)
 709  649  {
 710  650          static bool_t check_rpcbind = TRUE;
 711  651          CLIENT *client = NULL;
 712  652          RPCB parms;
 713  653          enum clnt_stat clnt_st;
 714  654          char *ua = NULL;
 715  655          uint_t vers;
 716  656          struct netbuf *address = NULL;
 717      -        uint_t start_vers = RPCBVERS4;
      657 +        void *handle;
      658 +        rpcb_entry_list_ptr relp = NULL;
      659 +        bool_t tmp_client = FALSE;
 718  660  
 719  661          /* parameter checking */
 720  662          if (nconf == NULL) {
 721  663                  rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
      664 +                /*
      665 +                 * Setting rpc_createerr.cf_stat is sufficient.
      666 +                 * No details in rpc_createerr.cf_error needed.
      667 +                 */
 722  668                  return (NULL);
 723  669          }
 724  670  
 725  671          parms.r_addr = NULL;
 726  672  
 727  673          /*
 728  674           * Use default total timeout if no timeout is specified.
 729  675           */
 730  676          if (tp == NULL)
 731  677                  tp = &tottimeout;
 732  678  
 733      -#ifdef PORTMAP
 734      -        /* Try version 2 for TCP or UDP */
 735      -        if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
 736      -                ushort_t port = 0;
 737      -                struct netbuf remote;
 738      -                uint_t pmapvers = 2;
 739      -                struct pmap pmapparms;
 740      -
 741      -                /*
 742      -                 * Try UDP only - there are some portmappers out
 743      -                 * there that use UDP only.
 744      -                 */
 745      -                if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
 746      -                        struct netconfig *newnconf;
 747      -                        void *handle;
 748      -
 749      -                        if ((handle = __rpc_setconf("udp")) == NULL) {
 750      -                                rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
 751      -                                return (NULL);
 752      -                        }
 753      -
 754      -                        /*
 755      -                         * The following to reinforce that you can
 756      -                         * only request for remote address through
 757      -                         * the same transport you are requesting.
 758      -                         * ie. requesting unversial address
 759      -                         * of IPv4 has to be carried through IPv4.
 760      -                         * Can't use IPv6 to send out the request.
 761      -                         * The mergeaddr in rpcbind can't handle
 762      -                         * this.
 763      -                         */
 764      -                        for (;;) {
 765      -                                if ((newnconf = __rpc_getconf(handle))
 766      -                                                                    == NULL) {
 767      -                                        __rpc_endconf(handle);
 768      -                                        rpc_createerr.cf_stat =
 769      -                                            RPC_UNKNOWNPROTO;
 770      -                                        return (NULL);
 771      -                                }
 772      -                                /*
 773      -                                 * here check the protocol family to
 774      -                                 * be consistent with the request one
 775      -                                 */
 776      -                                if (strcmp(newnconf->nc_protofmly,
 777      -                                    nconf->nc_protofmly) == NULL)
 778      -                                        break;
 779      -                        }
 780      -
 781      -                        client = _getclnthandle_timed(host, newnconf,
 782      -                                        &parms.r_addr, tp);
 783      -                        __rpc_endconf(handle);
 784      -                } else {
 785      -                        client = _getclnthandle_timed(host, nconf,
 786      -                                        &parms.r_addr, tp);
 787      -                }
 788      -                if (client == NULL)
 789      -                        return (NULL);
 790      -
 791      -                /*
 792      -                 * Set version and retry timeout.
 793      -                 */
 794      -                CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
 795      -                CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
 796      -
 797      -                pmapparms.pm_prog = program;
 798      -                pmapparms.pm_vers = version;
 799      -                pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
 800      -                                    IPPROTO_UDP : IPPROTO_TCP;
 801      -                pmapparms.pm_port = 0;  /* not needed */
 802      -                clnt_st = CLNT_CALL(client, PMAPPROC_GETPORT,
 803      -                                    (xdrproc_t)xdr_pmap, (caddr_t)&pmapparms,
 804      -                                    (xdrproc_t)xdr_u_short, (caddr_t)&port,
 805      -                                    *tp);
 806      -                if (clnt_st != RPC_SUCCESS) {
 807      -                        if ((clnt_st == RPC_PROGVERSMISMATCH) ||
 808      -                            (clnt_st == RPC_PROGUNAVAIL))
 809      -                                goto try_rpcbind; /* Try different versions */
 810      -                        rpc_createerr.cf_stat = RPC_PMAPFAILURE;
 811      -                        clnt_geterr(client, &rpc_createerr.cf_error);
 812      -                        goto error;
 813      -                } else if (port == 0) {
 814      -                        address = NULL;
 815      -                        rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
 816      -                        goto error;
 817      -                }
 818      -                port = htons(port);
 819      -                CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
 820      -                if (((address = malloc(sizeof (struct netbuf))) == NULL) ||
 821      -                    ((address->buf = malloc(remote.len)) == NULL)) {
 822      -                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
 823      -                        clnt_geterr(client, &rpc_createerr.cf_error);
 824      -                        if (address) {
 825      -                                free(address);
 826      -                                address = NULL;
 827      -                        }
 828      -                        goto error;
 829      -                }
 830      -                (void) memcpy(address->buf, remote.buf, remote.len);
 831      -                (void) memcpy(&address->buf[sizeof (short)], &port,
 832      -                                                                sizeof (short));
 833      -                address->len = address->maxlen = remote.len;
 834      -                goto done;
 835      -        }
 836      -#endif
 837      -
 838      -try_rpcbind:
 839  679          /*
 840  680           * Check if rpcbind is up.  This prevents needless delays when
 841  681           * accessing applications such as the keyserver while booting
 842  682           * disklessly.
 843  683           */
 844  684          if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
 845  685                  if (!__rpcbind_is_up()) {
 846  686                          rpc_createerr.cf_stat = RPC_PMAPFAILURE;
 847  687                          rpc_createerr.cf_error.re_errno = 0;
 848  688                          rpc_createerr.cf_error.re_terrno = 0;
 849  689                          goto error;
 850  690                  }
 851  691                  check_rpcbind = FALSE;
 852  692          }
 853  693  
 854  694          /*
 855      -         * Now we try version 4 and then 3.
 856      -         * We also send the remote system the address we used to
 857      -         * contact it in case it can help to connect back with us
      695 +         * First try version 4.
 858  696           */
 859  697          parms.r_prog = program;
 860  698          parms.r_vers = version;
 861  699          parms.r_owner = (char *)&nullstring[0]; /* not needed; */
 862  700          /* just for xdring */
 863  701          parms.r_netid = nconf->nc_netid; /* not really needed */
 864  702  
 865  703          /*
 866  704           * If a COTS transport is being used, try getting address via CLTS
 867  705           * transport.  This works only with version 4.
 868  706           */
 869  707          if (nconf->nc_semantics == NC_TPI_COTS_ORD ||
 870  708              nconf->nc_semantics == NC_TPI_COTS) {
 871      -                void *handle;
 872      -                struct netconfig *nconf_clts;
 873      -                rpcb_entry_list_ptr relp = NULL;
      709 +                tmp_client = TRUE;
      710 +                if ((handle = __rpc_setconf("datagram_v")) != NULL) {
      711 +                        struct netconfig *nconf_clts;
 874  712  
 875      -                if (client == NULL) {
 876      -                        /* This did not go through the above PORTMAP/TCP code */
 877      -                        if ((handle = __rpc_setconf("datagram_v")) != NULL) {
 878      -                                while ((nconf_clts = __rpc_getconf(handle))
 879      -                                    != NULL) {
 880      -                                        if (strcmp(nconf_clts->nc_protofmly,
 881      -                                            nconf->nc_protofmly) != 0) {
 882      -                                                continue;
 883      -                                        }
 884      -                                        client = _getclnthandle_timed(host,
 885      -                                                nconf_clts, &parms.r_addr,
 886      -                                                tp);
 887      -                                        break;
      713 +                        while ((nconf_clts = __rpc_getconf(handle)) != NULL) {
      714 +                                if (strcmp(nconf_clts->nc_protofmly,
      715 +                                    nconf->nc_protofmly) != 0) {
      716 +                                        continue;
 888  717                                  }
 889      -                                __rpc_endconf(handle);
      718 +                                /*
      719 +                                 * Sets rpc_createerr.cf_error members
      720 +                                 * on failure
      721 +                                 */
      722 +                                client = _getclnthandle_timed(host, nconf_clts,
      723 +                                    &parms.r_addr, tp);
      724 +                                break;
 890  725                          }
 891      -                        if (client == NULL)
 892      -                                goto regular_rpcbind;   /* Go the regular way */
 893      -                } else {
 894      -                        /* This is a UDP PORTMAP handle.  Change to version 4 */
 895      -                        vers = RPCBVERS4;
 896      -                        CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
      726 +                        __rpc_endconf(handle);
 897  727                  }
      728 +        } else {
      729 +                /* Sets rpc_createerr.cf_error members on failure */
      730 +                client = _getclnthandle_timed(host, nconf, &parms.r_addr, tp);
      731 +        }
      732 +
      733 +        if (client != NULL) {
      734 +
      735 +                /* Set rpcbind version 4 */
      736 +                vers = RPCBVERS4;
      737 +                CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
      738 +
 898  739                  /*
 899  740                   * We also send the remote system the address we used to
 900  741                   * contact it in case it can help it connect back with us
 901  742                   */
 902  743                  if (parms.r_addr == NULL) {
 903  744                          parms.r_addr = strdup(""); /* for XDRing */
 904  745                          if (parms.r_addr == NULL) {
 905  746                                  syslog(LOG_ERR, "__rpcb_findaddr_timed: "
 906      -                                        "strdup failed.");
      747 +                                    "strdup failed.");
      748 +                                /* Construct a system error */
      749 +                                rpc_createerr.cf_error.re_errno = errno;
      750 +                                rpc_createerr.cf_error.re_terrno = 0;
 907  751                                  rpc_createerr.cf_stat = RPC_SYSTEMERROR;
 908      -                                address = NULL;
 909  752                                  goto error;
 910  753                          }
 911  754                  }
 912  755  
 913      -                CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
      756 +                CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT,
      757 +                    (char *)&rpcbrmttime);
 914  758  
      759 +                /* Sets error structure members in client handle */
 915  760                  clnt_st = CLNT_CALL(client, RPCBPROC_GETADDRLIST,
 916      -                                    (xdrproc_t)xdr_rpcb, (char *)&parms,
 917      -                                    (xdrproc_t)xdr_rpcb_entry_list_ptr,
 918      -                                    (char *)&relp, *tp);
 919      -                if (clnt_st == RPC_SUCCESS) {
 920      -                        if (address = got_entry(relp, nconf)) {
 921      -                                xdr_free((xdrproc_t)xdr_rpcb_entry_list_ptr,
 922      -                                        (char *)&relp);
      761 +                    (xdrproc_t)xdr_rpcb, (char *)&parms,
      762 +                    (xdrproc_t)xdr_rpcb_entry_list_ptr, (char *)&relp, *tp);
      763 +
      764 +                switch (clnt_st) {
      765 +                case RPC_SUCCESS: /* Call succeeded */
      766 +                        address = got_entry(relp, nconf);
      767 +                        xdr_free((xdrproc_t)xdr_rpcb_entry_list_ptr,
      768 +                            (char *)&relp);
      769 +                        if (address != NULL) {
      770 +                                /* Program number and version number matched */
 923  771                                  goto done;
 924  772                          }
 925      -                        /* Entry not found for this transport */
 926      -                        xdr_free((xdrproc_t)xdr_rpcb_entry_list_ptr,
 927      -                                    (char *)&relp);
      773 +                        /* Program and version not found for this transport */
 928  774                          /*
 929      -                         * XXX: should have perhaps returned with error but
      775 +                         * XXX: should have returned with RPC_PROGUNAVAIL
      776 +                         * or perhaps RPC_PROGNOTREGISTERED error but
 930  777                           * since the remote machine might not always be able
 931  778                           * to send the address on all transports, we try the
 932      -                         * regular way with regular_rpcbind
      779 +                         * regular way with version 3, then 2
 933  780                           */
 934      -                        goto regular_rpcbind;
 935      -                } else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
 936      -                            (clnt_st == RPC_PROGUNAVAIL)) {
 937      -                        start_vers = RPCBVERS;  /* Try version 3 now */
 938      -                        goto regular_rpcbind; /* Try different versions */
 939      -                } else {
 940      -                        rpc_createerr.cf_stat = RPC_PMAPFAILURE;
      781 +                        /* Try the next version */
      782 +                        break;
      783 +                case RPC_PROGVERSMISMATCH: /* RPC protocol mismatch */
 941  784                          clnt_geterr(client, &rpc_createerr.cf_error);
      785 +                        if (rpc_createerr.cf_error.re_vers.low > vers) {
      786 +                                rpc_createerr.cf_stat = clnt_st;
      787 +                                goto error;  /* a new version, can't handle */
      788 +                        }
      789 +                        /* Try the next version */
      790 +                        break;
      791 +                case RPC_PROCUNAVAIL: /* Procedure unavailable */
      792 +                case RPC_PROGUNAVAIL: /* Program not available */
      793 +                case RPC_TIMEDOUT: /* Call timed out */
      794 +                        /* Try the next version */
      795 +                        break;
      796 +                default:
      797 +                        clnt_geterr(client, &rpc_createerr.cf_error);
      798 +                        rpc_createerr.cf_stat = RPC_PMAPFAILURE;
 942  799                          goto error;
      800 +                        break;
 943  801                  }
 944      -        }
 945  802  
 946      -regular_rpcbind:
      803 +        } else {
 947  804  
 948      -        /* Now the same transport is to be used to get the address */
 949      -        if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
 950      -            (nconf->nc_semantics == NC_TPI_COTS))) {
 951      -                /* A CLTS type of client - destroy it */
      805 +                /* No client */
      806 +                tmp_client = FALSE;
      807 +
      808 +        } /* End of version 4 */
      809 +
      810 +        /* Destroy a temporary client */
      811 +        if (client != NULL && tmp_client) {
 952  812                  CLNT_DESTROY(client);
 953  813                  client = NULL;
 954  814                  free(parms.r_addr);
 955  815                  parms.r_addr = NULL;
 956  816          }
      817 +        tmp_client = FALSE;
 957  818  
      819 +        /*
      820 +         * Try version 3
      821 +         */
      822 +
      823 +        /* Now the same transport is to be used to get the address */
 958  824          if (client == NULL) {
      825 +                /* Sets rpc_createerr.cf_error members on failure */
 959  826                  client = _getclnthandle_timed(host, nconf, &parms.r_addr, tp);
 960      -                if (client == NULL) {
 961      -                        address = NULL;
 962      -                        goto error;
 963      -                }
 964  827          }
 965      -        if (parms.r_addr == NULL) {
 966      -                parms.r_addr = strdup("");      /* for XDRing */
      828 +        address = NULL;
      829 +        if (client != NULL) {
 967  830                  if (parms.r_addr == NULL) {
 968      -                        syslog(LOG_ERR, "__rpcb_findaddr_timed: "
 969      -                                "strdup failed.");
 970      -                        address = NULL;
 971      -                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
 972      -                        goto error;
      831 +                        parms.r_addr = strdup("");      /* for XDRing */
      832 +                        if (parms.r_addr == NULL) {
      833 +                                syslog(LOG_ERR, "__rpcb_findaddr_timed: "
      834 +                                    "strdup failed.");
      835 +                                /* Construct a system error */
      836 +                                rpc_createerr.cf_error.re_errno = errno;
      837 +                                rpc_createerr.cf_error.re_terrno = 0;
      838 +                                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
      839 +                                goto error;
      840 +                        }
 973  841                  }
 974      -        }
 975  842  
 976      -        /* First try from start_vers and then version 3 (RPCBVERS) */
 977      -
 978      -        CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
 979      -        for (vers = start_vers;  vers >= RPCBVERS; vers--) {
 980      -                /* Set the version */
      843 +                CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT,
      844 +                    (char *)&rpcbrmttime);
      845 +                vers = RPCBVERS; /* Set the version */
 981  846                  CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
      847 +
      848 +                /* Sets error structure members in client handle */
 982  849                  clnt_st = CLNT_CALL(client, RPCBPROC_GETADDR,
 983      -                                    (xdrproc_t)xdr_rpcb, (char *)&parms,
 984      -                                    (xdrproc_t)xdr_wrapstring,
 985      -                                    (char *)&ua, *tp);
 986      -                if (clnt_st == RPC_SUCCESS) {
 987      -                        if ((ua == NULL) || (ua[0] == NULL)) {
 988      -                                if (ua != NULL)
 989      -                                        xdr_free(xdr_wrapstring, (char *)&ua);
      850 +                    (xdrproc_t)xdr_rpcb, (char *)&parms,
      851 +                    (xdrproc_t)xdr_wrapstring, (char *)&ua, *tp);
 990  852  
 991      -                                /* address unknown */
      853 +                switch (clnt_st) {
      854 +                case RPC_SUCCESS: /* Call succeeded */
      855 +                        if (ua != NULL) {
      856 +                                if (ua[0] != '\0') {
      857 +                                        address = uaddr2taddr(nconf, ua);
      858 +                                }
      859 +                                xdr_free((xdrproc_t)xdr_wrapstring,
      860 +                                    (char *)&ua);
      861 +
      862 +                                if (address != NULL) {
      863 +                                        goto done;
      864 +                                }
      865 +                                /* NULL universal address */
      866 +                                /* But client call was successful */
      867 +                                clnt_geterr(client, &rpc_createerr.cf_error);
 992  868                                  rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
 993  869                                  goto error;
 994  870                          }
 995      -                        address = uaddr2taddr(nconf, ua);
 996      -#ifdef ND_DEBUG
 997      -                        fprintf(stderr, "\tRemote address is [%s]\n", ua);
 998      -                        if (!address)
 999      -                                fprintf(stderr,
1000      -                                        "\tCouldn't resolve remote address!\n");
      871 +#ifndef PORTMAP
      872 +                        clnt_geterr(client, &rpc_createerr.cf_error);
      873 +                        rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
      874 +                        goto error;
1001  875  #endif
1002      -                        xdr_free((xdrproc_t)xdr_wrapstring, (char *)&ua);
      876 +                        /* Try the next version */
      877 +                        break;
      878 +                case RPC_PROGVERSMISMATCH: /* RPC protocol mismatch */
      879 +                        clnt_geterr(client, &rpc_createerr.cf_error);
      880 +#ifdef PORTMAP
      881 +                        if (rpc_createerr.cf_error.re_vers.low > vers) {
      882 +                                rpc_createerr.cf_stat = clnt_st;
      883 +                                goto error;  /* a new version, can't handle */
      884 +                        }
      885 +#else
      886 +                        rpc_createerr.cf_stat = clnt_st;
      887 +                        goto error;
      888 +#endif
      889 +                        /* Try the next version */
      890 +                        break;
      891 +#ifdef PORTMAP
      892 +                case RPC_PROCUNAVAIL: /* Procedure unavailable */
      893 +                case RPC_PROGUNAVAIL: /* Program not available */
      894 +                case RPC_TIMEDOUT: /* Call timed out */
      895 +                        /* Try the next version */
      896 +                        break;
      897 +#endif
      898 +                default:
      899 +                        clnt_geterr(client, &rpc_createerr.cf_error);
      900 +                        rpc_createerr.cf_stat = RPC_PMAPFAILURE;
      901 +                        goto error;
      902 +                        break;
      903 +                }
      904 +        } /* End of version 3 */
      905 +#ifndef PORTMAP
      906 +        /* cf_error members set by creation failure */
      907 +        rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
      908 +#endif
      909 +        /*
      910 +         * Try version 2
      911 +         */
1003  912  
1004      -                        if (!address) {
1005      -                                /* We don't know about your universal address */
1006      -                                rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
      913 +#ifdef PORTMAP
      914 +        /* Try version 2 for TCP or UDP */
      915 +        if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
      916 +                ushort_t port = 0;
      917 +                struct netbuf remote;
      918 +                uint_t pmapvers = 2;
      919 +                struct pmap pmapparms;
      920 +
      921 +                /*
      922 +                 * Try UDP only - there are some portmappers out
      923 +                 * there that use UDP only.
      924 +                 */
      925 +                if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
      926 +                        struct netconfig *newnconf;
      927 +
      928 +                        if (client != NULL) {
      929 +                                CLNT_DESTROY(client);
      930 +                                client = NULL;
      931 +                                free(parms.r_addr);
      932 +                                parms.r_addr = NULL;
      933 +                        }
      934 +                        if ((handle = __rpc_setconf("udp")) == NULL) {
      935 +                                /* Construct an unknown protocol error */
      936 +                                rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1007  937                                  goto error;
1008  938                          }
1009      -                        goto done;
      939 +
      940 +                        /*
      941 +                         * The following to reinforce that you can
      942 +                         * only request for remote address through
      943 +                         * the same transport you are requesting.
      944 +                         * ie. requesting unversial address
      945 +                         * of IPv4 has to be carried through IPv4.
      946 +                         * Can't use IPv6 to send out the request.
      947 +                         * The mergeaddr in rpcbind can't handle
      948 +                         * this.
      949 +                         */
      950 +                        for (;;) {
      951 +                                if ((newnconf = __rpc_getconf(handle))
      952 +                                    == NULL) {
      953 +                                        __rpc_endconf(handle);
      954 +                                        /*
      955 +                                         * Construct an unknown protocol
      956 +                                         * error
      957 +                                         */
      958 +                                        rpc_createerr.cf_stat =
      959 +                                            RPC_UNKNOWNPROTO;
      960 +                                        goto error;
      961 +                                }
      962 +                                /*
      963 +                                 * here check the protocol family to
      964 +                                 * be consistent with the request one
      965 +                                 */
      966 +                                if (strcmp(newnconf->nc_protofmly,
      967 +                                    nconf->nc_protofmly) == 0)
      968 +                                        break;
      969 +                        }
      970 +
      971 +                        /* Sets rpc_createerr.cf_error members on failure */
      972 +                        client = _getclnthandle_timed(host, newnconf,
      973 +                            &parms.r_addr, tp);
      974 +                        __rpc_endconf(handle);
      975 +                        tmp_client = TRUE;
1010  976                  }
1011      -                if (clnt_st == RPC_PROGVERSMISMATCH) {
1012      -                        struct rpc_err rpcerr;
      977 +                if (client == NULL) {
      978 +                        /*
      979 +                         * rpc_createerr. cf_error members were set by
      980 +                         * creation failure
      981 +                         */
      982 +                        rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
      983 +                        tmp_client = FALSE;
      984 +                        goto error;
      985 +                }
1013  986  
1014      -                        clnt_geterr(client, &rpcerr);
1015      -                        if (rpcerr.re_vers.low > RPCBVERS4)
1016      -                                goto error;  /* a new version, can't handle */
1017      -                } else if (clnt_st != RPC_PROGUNAVAIL) {
1018      -                        /* Cant handle this error */
      987 +                /*
      988 +                 * Set version and retry timeout.
      989 +                 */
      990 +                CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
      991 +                CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
      992 +
      993 +                pmapparms.pm_prog = program;
      994 +                pmapparms.pm_vers = version;
      995 +                pmapparms.pm_prot = (strcmp(nconf->nc_proto, NC_TCP) != 0) ?
      996 +                    IPPROTO_UDP : IPPROTO_TCP;
      997 +                pmapparms.pm_port = 0;  /* not needed */
      998 +
      999 +                /* Sets error structure members in client handle */
     1000 +                clnt_st = CLNT_CALL(client, PMAPPROC_GETPORT,
     1001 +                    (xdrproc_t)xdr_pmap, (caddr_t)&pmapparms,
     1002 +                    (xdrproc_t)xdr_u_short, (caddr_t)&port, *tp);
     1003 +
     1004 +                if (clnt_st != RPC_SUCCESS) {
     1005 +                        clnt_geterr(client, &rpc_createerr.cf_error);
     1006 +                        rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1019 1007                          goto error;
     1008 +                } else if (port == 0) {
     1009 +                        /* Will be NULL universal address */
     1010 +                        /* But client call was successful */
     1011 +                        clnt_geterr(client, &rpc_createerr.cf_error);
     1012 +                        rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
     1013 +                        goto error;
1020 1014                  }
     1015 +                port = htons(port);
     1016 +                CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
     1017 +                if (((address = malloc(sizeof (struct netbuf))) == NULL) ||
     1018 +                    ((address->buf = malloc(remote.len)) == NULL)) {
     1019 +                        /* Construct a system error */
     1020 +                        rpc_createerr.cf_error.re_errno = errno;
     1021 +                        rpc_createerr.cf_error.re_terrno = 0;
     1022 +                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
     1023 +                        free(address);
     1024 +                        address = NULL;
     1025 +                        goto error;
     1026 +                }
     1027 +                (void) memcpy(address->buf, remote.buf, remote.len);
     1028 +                (void) memcpy(&address->buf[sizeof (short)], &port,
     1029 +                    sizeof (short));
     1030 +                address->len = address->maxlen = remote.len;
     1031 +                goto done;
     1032 +        } else {
     1033 +                /*
     1034 +                 * This is not NC_INET.
     1035 +                 * Always an error for version 2.
     1036 +                 */
     1037 +                if (client != NULL && clnt_st != RPC_SUCCESS) {
     1038 +                        /* There is a client that failed */
     1039 +                        clnt_geterr(client, &rpc_createerr.cf_error);
     1040 +                        rpc_createerr.cf_stat = clnt_st;
     1041 +                } else {
     1042 +                        /* Something else */
     1043 +                        rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
     1044 +                        /*
     1045 +                         * Setting rpc_createerr.cf_stat is sufficient.
     1046 +                         * No details in rpc_createerr.cf_error needed.
     1047 +                         */
     1048 +                }
1021 1049          }
     1050 +#endif
1022 1051  
1023      -        if ((address == NULL) || (address->len == 0)) {
1024      -                rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
1025      -                clnt_geterr(client, &rpc_createerr.cf_error);
1026      -        }
1027      -
1028 1052  error:
1029      -        if (client) {
     1053 +        /* Return NULL address and NULL client */
     1054 +        address = NULL;
     1055 +        if (client != NULL) {
1030 1056                  CLNT_DESTROY(client);
1031 1057                  client = NULL;
1032 1058          }
     1059 +
1033 1060  done:
1034      -        if (nconf->nc_semantics != NC_TPI_CLTS) {
1035      -                /* This client is the connectionless one */
1036      -                if (client) {
1037      -                        CLNT_DESTROY(client);
1038      -                        client = NULL;
1039      -                }
     1061 +        /* Return an address and optional client */
     1062 +        if (client != NULL && tmp_client) {
     1063 +                /* This client is the temporary one */
     1064 +                CLNT_DESTROY(client);
     1065 +                client = NULL;
1040 1066          }
1041      -        if (clpp) {
     1067 +        if (clpp != NULL) {
1042 1068                  *clpp = client;
1043      -        } else if (client) {
     1069 +        } else if (client != NULL) {
1044 1070                  CLNT_DESTROY(client);
1045 1071          }
1046      -        if (parms.r_addr)
1047      -                free(parms.r_addr);
     1072 +        free(parms.r_addr);
1048 1073          return (address);
1049 1074  }
1050 1075  
1051 1076  
1052 1077  /*
1053 1078   * Find the mapped address for program, version.
1054 1079   * Calls the rpcbind service remotely to do the lookup.
1055 1080   * Uses the transport specified in nconf.
1056 1081   * Returns FALSE (0) if no map exists, else returns 1.
1057 1082   *
↓ open down ↓ 30 lines elided ↑ open up ↑
1088 1113   */
1089 1114  rpcblist *
1090 1115  rpcb_getmaps(const struct netconfig *nconf, const char *host)
1091 1116  {
1092 1117          rpcblist_ptr head = NULL;
1093 1118          CLIENT *client;
1094 1119          enum clnt_stat clnt_st;
1095 1120          int vers = 0;
1096 1121  
1097 1122          client = getclnthandle((char *)host,
1098      -                        (struct netconfig *)nconf, NULL);
     1123 +            (struct netconfig *)nconf, NULL);
1099 1124          if (client == NULL)
1100 1125                  return (NULL);
1101 1126  
1102 1127          clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
1103      -                        (xdrproc_t)xdr_void, NULL,
1104      -                        (xdrproc_t)xdr_rpcblist_ptr,
1105      -                        (char *)&head, tottimeout);
     1128 +            (xdrproc_t)xdr_void, NULL,
     1129 +            (xdrproc_t)xdr_rpcblist_ptr,
     1130 +            (char *)&head, tottimeout);
1106 1131          if (clnt_st == RPC_SUCCESS)
1107 1132                  goto done;
1108 1133  
1109 1134          if ((clnt_st != RPC_PROGVERSMISMATCH) &&
1110      -                    (clnt_st != RPC_PROGUNAVAIL)) {
     1135 +            (clnt_st != RPC_PROGUNAVAIL)) {
1111 1136                  rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1112 1137                  clnt_geterr(client, &rpc_createerr.cf_error);
1113 1138                  goto done;
1114 1139          }
1115 1140  
1116 1141          /* fall back to earlier version */
1117 1142          CLNT_CONTROL(client, CLGET_VERS, (char *)&vers);
1118 1143          if (vers == RPCBVERS4) {
1119 1144                  vers = RPCBVERS;
1120 1145                  CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
1121 1146                  if (CLNT_CALL(client, RPCBPROC_DUMP,
1122      -                        (xdrproc_t)xdr_void,
1123      -                        NULL, (xdrproc_t)xdr_rpcblist_ptr,
1124      -                        (char *)&head, tottimeout) == RPC_SUCCESS)
     1147 +                    (xdrproc_t)xdr_void,
     1148 +                    NULL, (xdrproc_t)xdr_rpcblist_ptr,
     1149 +                    (char *)&head, tottimeout) == RPC_SUCCESS)
1125 1150                                  goto done;
1126 1151          }
1127 1152          rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1128 1153          clnt_geterr(client, &rpc_createerr.cf_error);
1129 1154  
1130 1155  done:
1131 1156          CLNT_DESTROY(client);
1132 1157          return (head);
1133 1158  }
1134 1159  
↓ open down ↓ 25 lines elided ↑ open up ↑
1160 1185          a.proc = proc;
1161 1186          a.args.args_val = argsp;
1162 1187          a.xdr_args = xdrargs;
1163 1188          r.addr = NULL;
1164 1189          r.results.results_val = resp;
1165 1190          r.xdr_res = xdrres;
1166 1191  
1167 1192          for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
1168 1193                  CLNT_CONTROL(client, CLSET_VERS, (char *)&rpcb_vers);
1169 1194                  stat = CLNT_CALL(client, RPCBPROC_CALLIT,
1170      -                        (xdrproc_t)xdr_rpcb_rmtcallargs, (char *)&a,
1171      -                        (xdrproc_t)xdr_rpcb_rmtcallres, (char *)&r, tout);
     1195 +                    (xdrproc_t)xdr_rpcb_rmtcallargs, (char *)&a,
     1196 +                    (xdrproc_t)xdr_rpcb_rmtcallres, (char *)&r, tout);
1172 1197                  if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
1173 1198                          struct netbuf *na;
1174 1199  
1175 1200                          na = uaddr2taddr((struct netconfig *)nconf, r.addr);
1176 1201                          if (!na) {
1177 1202                                  stat = RPC_N2AXLATEFAILURE;
1178 1203                                  ((struct netbuf *)addr_ptr)->len = 0;
1179 1204                                  goto error;
1180 1205                          }
1181 1206                          if (na->len > addr_ptr->maxlen) {
↓ open down ↓ 2 lines elided ↑ open up ↑
1184 1209                                  netdir_free((char *)na, ND_ADDR);
1185 1210                                  ((struct netbuf *)addr_ptr)->len = 0;
1186 1211                                  goto error;
1187 1212                          }
1188 1213                          (void) memcpy(addr_ptr->buf, na->buf, (int)na->len);
1189 1214                          ((struct netbuf *)addr_ptr)->len = na->len;
1190 1215                          netdir_free((char *)na, ND_ADDR);
1191 1216                          break;
1192 1217                  }
1193 1218                  if ((stat != RPC_PROGVERSMISMATCH) &&
1194      -                            (stat != RPC_PROGUNAVAIL))
     1219 +                    (stat != RPC_PROGUNAVAIL))
1195 1220                          goto error;
1196 1221          }
1197 1222  error:
1198 1223          CLNT_DESTROY(client);
1199 1224          if (r.addr)
1200 1225                  xdr_free((xdrproc_t)xdr_wrapstring, (char *)&r.addr);
1201 1226          return (stat);
1202 1227  }
1203 1228  
1204 1229  /*
↓ open down ↓ 27 lines elided ↑ open up ↑
1232 1257                  }
1233 1258                  client = getclnthandle((char *)host, nconf, NULL);
1234 1259                  if (client)
1235 1260                          break;
1236 1261          }
1237 1262          __rpc_endconf(handle);
1238 1263          if (client == NULL)
1239 1264                  return (FALSE);
1240 1265  
1241 1266          st = CLNT_CALL(client, RPCBPROC_GETTIME,
1242      -                (xdrproc_t)xdr_void, NULL,
1243      -                (xdrproc_t)xdr_time_t, (char *)timep, tottimeout);
     1267 +            (xdrproc_t)xdr_void, NULL,
     1268 +            (xdrproc_t)xdr_time_t, (char *)timep, tottimeout);
1244 1269  
1245 1270          if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
1246 1271                  CLNT_CONTROL(client, CLGET_VERS, (char *)&vers);
1247 1272                  if (vers == RPCBVERS4) {
1248 1273                          /* fall back to earlier version */
1249 1274                          vers = RPCBVERS;
1250 1275                          CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
1251 1276                          st = CLNT_CALL(client, RPCBPROC_GETTIME,
1252      -                                (xdrproc_t)xdr_void, NULL,
1253      -                                (xdrproc_t)xdr_time_t, (char *)timep,
1254      -                                tottimeout);
     1277 +                            (xdrproc_t)xdr_void, NULL,
     1278 +                            (xdrproc_t)xdr_time_t, (char *)timep,
     1279 +                            tottimeout);
1255 1280                  }
1256 1281          }
1257 1282          CLNT_DESTROY(client);
1258 1283          return (st == RPC_SUCCESS? TRUE : FALSE);
1259 1284  }
1260 1285  
1261 1286  /*
1262 1287   * Converts taddr to universal address.  This routine should never
1263 1288   * really be called because local n2a libraries are always provided.
1264 1289   */
↓ open down ↓ 10 lines elided ↑ open up ↑
1275 1300          }
1276 1301          if (taddr == NULL) {
1277 1302                  rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1278 1303                  return (NULL);
1279 1304          }
1280 1305          client = local_rpcb();
1281 1306          if (!client)
1282 1307                  return (NULL);
1283 1308  
1284 1309          CLNT_CALL(client, RPCBPROC_TADDR2UADDR, (xdrproc_t)xdr_netbuf,
1285      -                (char *)taddr, (xdrproc_t)xdr_wrapstring, (char *)&uaddr,
1286      -                tottimeout);
     1310 +            (char *)taddr, (xdrproc_t)xdr_wrapstring, (char *)&uaddr,
     1311 +            tottimeout);
1287 1312          CLNT_DESTROY(client);
1288 1313          return (uaddr);
1289 1314  }
1290 1315  
1291 1316  /*
1292 1317   * Converts universal address to netbuf.  This routine should never
1293 1318   * really be called because local n2a libraries are always provided.
1294 1319   */
1295 1320  struct netbuf *
1296 1321  rpcb_uaddr2taddr(struct netconfig *nconf, char *uaddr)
↓ open down ↓ 14 lines elided ↑ open up ↑
1311 1336          if (!client)
1312 1337                  return (NULL);
1313 1338  
1314 1339          taddr = calloc(1, sizeof (struct netbuf));
1315 1340          if (taddr == NULL) {
1316 1341                  CLNT_DESTROY(client);
1317 1342                  return (NULL);
1318 1343          }
1319 1344  
1320 1345          if (CLNT_CALL(client, RPCBPROC_UADDR2TADDR, (xdrproc_t)xdr_wrapstring,
1321      -                (char *)&uaddr, (xdrproc_t)xdr_netbuf, (char *)taddr,
1322      -                tottimeout) != RPC_SUCCESS) {
     1346 +            (char *)&uaddr, (xdrproc_t)xdr_netbuf, (char *)taddr,
     1347 +            tottimeout) != RPC_SUCCESS) {
1323 1348                  free(taddr);
1324 1349                  taddr = NULL;
1325 1350          }
1326 1351          CLNT_DESTROY(client);
1327 1352          return (taddr);
1328 1353  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX