(root)/
glibc-2.38/
sunrpc/
pm_getport.c
       1  /*
       2   * pmap_getport.c
       3   * Client interface to pmap rpc service.
       4   *
       5   * Copyright (c) 2010, Oracle America, Inc.
       6   *
       7   * Redistribution and use in source and binary forms, with or without
       8   * modification, are permitted provided that the following conditions are
       9   * met:
      10   *
      11   *     * Redistributions of source code must retain the above copyright
      12   *       notice, this list of conditions and the following disclaimer.
      13   *     * Redistributions in binary form must reproduce the above
      14   *       copyright notice, this list of conditions and the following
      15   *       disclaimer in the documentation and/or other materials
      16   *       provided with the distribution.
      17   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      18   *       contributors may be used to endorse or promote products derived
      19   *       from this software without specific prior written permission.
      20   *
      21   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      22   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      23   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      24   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      25   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      26   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      27   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      28   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      30   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      31   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      32   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      33   */
      34  
      35  #include <stdbool.h>
      36  #include <unistd.h>
      37  #include <rpc/rpc.h>
      38  #include <rpc/pmap_prot.h>
      39  #include <rpc/pmap_clnt.h>
      40  #include <sys/socket.h>
      41  #include <shlib-compat.h>
      42  
      43  /*
      44   * Create a socket that is locally bound to a non-reserve port. For
      45   * any failures, -1 is returned which will cause the RPC code to
      46   * create the socket.
      47   */
      48  int
      49  __get_socket (struct sockaddr_in *saddr)
      50  {
      51    int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      52    if (so < 0)
      53      return -1;
      54  
      55    struct sockaddr_in laddr;
      56    socklen_t namelen = sizeof (laddr);
      57    laddr.sin_family = AF_INET;
      58    laddr.sin_port = 0;
      59    laddr.sin_addr.s_addr = htonl (INADDR_ANY);
      60  
      61    int cc = __bind (so, (struct sockaddr *) &laddr, namelen);
      62    if (__glibc_unlikely (cc < 0))
      63      {
      64      fail:
      65        __close (so);
      66        return -1;
      67      }
      68  
      69    cc = __connect (so, (struct sockaddr *) saddr, namelen);
      70    if (__glibc_unlikely (cc < 0))
      71      goto fail;
      72  
      73    return so;
      74  }
      75  
      76  
      77  /*
      78   * Find the mapped port for program,version.
      79   * Internal version with additional parameters.
      80   * Calls the pmap service remotely to do the lookup.
      81   * Returns 0 if no map exists.
      82   */
      83  u_short
      84  __libc_rpc_getport (struct sockaddr_in *address, u_long program,
      85  		    u_long version, u_int protocol, time_t timeout_sec,
      86  		    time_t tottimeout_sec)
      87  {
      88    const struct timeval timeout = {timeout_sec, 0};
      89    const struct timeval tottimeout = {tottimeout_sec, 0};
      90  
      91    u_short port = 0;
      92    int socket = -1;
      93    CLIENT *client;
      94    struct pmap parms;
      95    bool closeit = false;
      96  
      97    address->sin_port = htons (PMAPPORT);
      98    if (protocol == IPPROTO_TCP)
      99      {
     100        /* Don't need a reserved port to get ports from the portmapper.  */
     101        socket = __get_socket(address);
     102        if (socket != -1)
     103  	closeit = true;
     104        client = clnttcp_create (address, PMAPPROG, PMAPVERS, &socket,
     105  			       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
     106      }
     107    else
     108      client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout,
     109  				&socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
     110    if (client != (CLIENT *) NULL)
     111      {
     112        struct rpc_createerr *ce = &get_rpc_createerr ();
     113        parms.pm_prog = program;
     114        parms.pm_vers = version;
     115        parms.pm_prot = protocol;
     116        parms.pm_port = 0;	/* not needed or used */
     117        if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
     118  		     (caddr_t)&parms, (xdrproc_t)xdr_u_short,
     119  		     (caddr_t)&port, tottimeout) != RPC_SUCCESS)
     120  	{
     121  	  ce->cf_stat = RPC_PMAPFAILURE;
     122  	  clnt_geterr (client, &ce->cf_error);
     123  	}
     124        else if (port == 0)
     125  	{
     126  	  ce->cf_stat = RPC_PROGNOTREGISTERED;
     127  	}
     128        CLNT_DESTROY (client);
     129      }
     130    /* We only need to close the socket here if we opened  it.  */
     131    if (closeit)
     132      (void) __close (socket);
     133    address->sin_port = 0;
     134    return port;
     135  }
     136  #ifdef EXPORT_RPC_SYMBOLS
     137  libc_hidden_def (__libc_rpc_getport)
     138  #else
     139  libc_hidden_nolink_sunrpc (__libc_rpc_getport, GLIBC_PRIVATE)
     140  #endif
     141  
     142  
     143  /*
     144   * Find the mapped port for program,version.
     145   * Calls the pmap service remotely to do the lookup.
     146   * Returns 0 if no map exists.
     147   */
     148  u_short
     149  pmap_getport (struct sockaddr_in *address, u_long program, u_long version,
     150  	      u_int protocol)
     151  {
     152    return __libc_rpc_getport (address, program, version, protocol, 5, 60);
     153  }
     154  libc_hidden_nolink_sunrpc (pmap_getport, GLIBC_2_0)