(root)/
glibc-2.38/
sunrpc/
pmap_clnt.c
       1  /*
       2   * Copyright (c) 2010, Oracle America, Inc.
       3   *
       4   * Redistribution and use in source and binary forms, with or without
       5   * modification, are permitted provided that the following conditions are
       6   * met:
       7   *
       8   *     * Redistributions of source code must retain the above copyright
       9   *       notice, this list of conditions and the following disclaimer.
      10   *     * Redistributions in binary form must reproduce the above
      11   *       copyright notice, this list of conditions and the following
      12   *       disclaimer in the documentation and/or other materials
      13   *       provided with the distribution.
      14   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      15   *       contributors may be used to endorse or promote products derived
      16   *       from this software without specific prior written permission.
      17   *
      18   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      21   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      22   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      23   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      25   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      27   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      28   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30   */
      31  /*
      32   * pmap_clnt.c
      33   * Client interface to pmap rpc service.
      34   */
      35  
      36  #include <stdio.h>
      37  #include <unistd.h>
      38  #include <libintl.h>
      39  #include <net/if.h>
      40  #include <ifaddrs.h>
      41  #include <sys/ioctl.h>
      42  #include <sys/socket.h>
      43  #include <netinet/in.h>
      44  #include <arpa/inet.h>
      45  #include <rpc/rpc.h>
      46  #include <rpc/pmap_prot.h>
      47  #include <rpc/pmap_clnt.h>
      48  #include <shlib-compat.h>
      49  
      50  /*
      51   * Same as get_myaddress, but we try to use the loopback
      52   * interface. portmap caches interfaces, and on DHCP clients,
      53   * it could be that only loopback is started at this time.
      54   */
      55  static bool_t
      56  __get_myaddress (struct sockaddr_in *addr)
      57  {
      58    struct ifaddrs *ifa;
      59  
      60    if (getifaddrs (&ifa) != 0)
      61      {
      62        perror ("get_myaddress: getifaddrs");
      63        exit (1);
      64      }
      65  
      66    int loopback = 1;
      67    struct ifaddrs *run;
      68  
      69   again:
      70    run = ifa;
      71    while (run != NULL)
      72      {
      73        if ((run->ifa_flags & IFF_UP)
      74  	  && run->ifa_addr != NULL
      75  	  && run->ifa_addr->sa_family == AF_INET
      76  	  && ((run->ifa_flags & IFF_LOOPBACK) || loopback == 0))
      77  	{
      78  	  *addr = *((struct sockaddr_in *) run->ifa_addr);
      79  	  addr->sin_port = htons (PMAPPORT);
      80  	  goto out;
      81  	}
      82  
      83        run = run->ifa_next;
      84      }
      85  
      86    if (loopback == 1)
      87      {
      88        loopback = 0;
      89        goto again;
      90      }
      91   out:
      92    freeifaddrs (ifa);
      93  
      94    return run == NULL ? FALSE : TRUE;
      95  }
      96  
      97  
      98  static const struct timeval timeout = {5, 0};
      99  static const struct timeval tottimeout = {60, 0};
     100  
     101  /*
     102   * Set a mapping between program,version and port.
     103   * Calls the pmap service remotely to do the mapping.
     104   */
     105  bool_t
     106  pmap_set (u_long program, u_long version, int protocol, u_short port)
     107  {
     108    struct sockaddr_in myaddress;
     109    int socket = -1;
     110    CLIENT *client;
     111    struct pmap parms;
     112    bool_t rslt;
     113  
     114    if (!__get_myaddress (&myaddress))
     115      return FALSE;
     116    client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, timeout, &socket,
     117  			      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
     118    if (client == (CLIENT *) NULL)
     119      return (FALSE);
     120    parms.pm_prog = program;
     121    parms.pm_vers = version;
     122    parms.pm_prot = protocol;
     123    parms.pm_port = port;
     124    if (CLNT_CALL (client, PMAPPROC_SET, (xdrproc_t)xdr_pmap,
     125  		 (caddr_t)&parms, (xdrproc_t)xdr_bool, (caddr_t)&rslt,
     126  		 tottimeout) != RPC_SUCCESS)
     127      {
     128        clnt_perror (client, _("Cannot register service"));
     129        rslt = FALSE;
     130      }
     131    CLNT_DESTROY (client);
     132    /* (void)close(socket); CLNT_DESTROY closes it */
     133    return rslt;
     134  }
     135  libc_hidden_nolink_sunrpc (pmap_set, GLIBC_2_0)
     136  
     137  /*
     138   * Remove the mapping between program,version and port.
     139   * Calls the pmap service remotely to do the un-mapping.
     140   */
     141  bool_t
     142  pmap_unset (u_long program, u_long version)
     143  {
     144    struct sockaddr_in myaddress;
     145    int socket = -1;
     146    CLIENT *client;
     147    struct pmap parms;
     148    bool_t rslt;
     149  
     150    if (!__get_myaddress (&myaddress))
     151      return FALSE;
     152    client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, timeout, &socket,
     153  			      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
     154    if (client == (CLIENT *) NULL)
     155      return FALSE;
     156    parms.pm_prog = program;
     157    parms.pm_vers = version;
     158    parms.pm_port = parms.pm_prot = 0;
     159    CLNT_CALL (client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap,
     160  	     (caddr_t)&parms, (xdrproc_t)xdr_bool, (caddr_t)&rslt,
     161  	     tottimeout);
     162    CLNT_DESTROY (client);
     163    /* (void)close(socket); CLNT_DESTROY already closed it */
     164    return rslt;
     165  }
     166  libc_hidden_nolink_sunrpc (pmap_unset, GLIBC_2_0)