chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / sunrpc / pm_getport.c
1 /*
2  * pmap_getport.c
3  * Client interface to pmap rpc service.
4  *
5  * Copyright (C) 1984, Sun Microsystems, 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 Sun Microsystems, 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
42 static const struct timeval timeout =
43 {5, 0};
44 static const struct timeval tottimeout =
45 {60, 0};
46
47 /*
48  * Create a socket that is locally bound to a non-reserve port. For
49  * any failures, -1 is returned which will cause the RPC code to
50  * create the socket.
51  */
52 int
53 internal_function
54 __get_socket (struct sockaddr_in *saddr)
55 {
56   int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
57   if (so < 0)
58     return -1;
59
60   struct sockaddr_in laddr;
61   socklen_t namelen = sizeof (laddr);
62   laddr.sin_family = AF_INET;
63   laddr.sin_port = 0;
64   laddr.sin_addr.s_addr = htonl (INADDR_ANY);
65
66   int cc = __bind (so, (struct sockaddr *) &laddr, namelen);
67   if (__builtin_expect (cc < 0, 0))
68     {
69     fail:
70       __close (so);
71       return -1;
72     }
73
74   cc = __connect (so, (struct sockaddr *) saddr, namelen);
75   if (__builtin_expect (cc < 0, 0))
76     goto fail;
77
78   return so;
79 }
80
81
82 /*
83  * Find the mapped port for program,version.
84  * Calls the pmap service remotely to do the lookup.
85  * Returns 0 if no map exists.
86  */
87 u_short
88 pmap_getport (address, program, version, protocol)
89      struct sockaddr_in *address;
90      u_long program;
91      u_long version;
92      u_int protocol;
93 {
94   u_short port = 0;
95   int socket = -1;
96   CLIENT *client;
97   struct pmap parms;
98   bool closeit = false;
99
100   address->sin_port = htons (PMAPPORT);
101   if (protocol == IPPROTO_TCP)
102     {
103       /* Don't need a reserved port to get ports from the portmapper.  */
104       socket = __get_socket(address);
105       if (socket != -1)
106         closeit = true;
107       client = INTUSE(clnttcp_create) (address, PMAPPROG, PMAPVERS, &socket,
108                                        RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
109     }
110   else
111     client = INTUSE(clntudp_bufcreate) (address, PMAPPROG, PMAPVERS, timeout,
112                                         &socket, RPCSMALLMSGSIZE,
113                                         RPCSMALLMSGSIZE);
114   if (client != (CLIENT *) NULL)
115     {
116       struct rpc_createerr *ce = &get_rpc_createerr ();
117       parms.pm_prog = program;
118       parms.pm_vers = version;
119       parms.pm_prot = protocol;
120       parms.pm_port = 0;        /* not needed or used */
121       if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)INTUSE(xdr_pmap),
122                      (caddr_t)&parms, (xdrproc_t)INTUSE(xdr_u_short),
123                      (caddr_t)&port, tottimeout) != RPC_SUCCESS)
124         {
125           ce->cf_stat = RPC_PMAPFAILURE;
126           clnt_geterr (client, &ce->cf_error);
127         }
128       else if (port == 0)
129         {
130           ce->cf_stat = RPC_PROGNOTREGISTERED;
131         }
132       CLNT_DESTROY (client);
133     }
134   /* We only need to close the socket here if we opened  it.  */
135   if (closeit)
136     (void) __close (socket);
137   address->sin_port = 0;
138   return port;
139 }
140 libc_hidden_def (pmap_getport)