aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c97
1 files changed, 83 insertions, 14 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index c652e4cc9fe9..9a80a922c527 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/socket.h> 18#include <linux/socket.h>
19#include <linux/un.h>
19#include <linux/in.h> 20#include <linux/in.h>
20#include <linux/in6.h> 21#include <linux/in6.h>
21#include <linux/kernel.h> 22#include <linux/kernel.h>
@@ -32,6 +33,8 @@
32# define RPCDBG_FACILITY RPCDBG_BIND 33# define RPCDBG_FACILITY RPCDBG_BIND
33#endif 34#endif
34 35
36#define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock"
37
35#define RPCBIND_PROGRAM (100000u) 38#define RPCBIND_PROGRAM (100000u)
36#define RPCBIND_PORT (111u) 39#define RPCBIND_PORT (111u)
37 40
@@ -158,20 +161,69 @@ static void rpcb_map_release(void *data)
158 kfree(map); 161 kfree(map);
159} 162}
160 163
161static const struct sockaddr_in rpcb_inaddr_loopback = { 164/*
162 .sin_family = AF_INET, 165 * Returns zero on success, otherwise a negative errno value
163 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 166 * is returned.
164 .sin_port = htons(RPCBIND_PORT), 167 */
165}; 168static int rpcb_create_local_unix(void)
169{
170 static const struct sockaddr_un rpcb_localaddr_rpcbind = {
171 .sun_family = AF_LOCAL,
172 .sun_path = RPCBIND_SOCK_PATHNAME,
173 };
174 struct rpc_create_args args = {
175 .net = &init_net,
176 .protocol = XPRT_TRANSPORT_LOCAL,
177 .address = (struct sockaddr *)&rpcb_localaddr_rpcbind,
178 .addrsize = sizeof(rpcb_localaddr_rpcbind),
179 .servername = "localhost",
180 .program = &rpcb_program,
181 .version = RPCBVERS_2,
182 .authflavor = RPC_AUTH_NULL,
183 };
184 struct rpc_clnt *clnt, *clnt4;
185 int result = 0;
186
187 /*
188 * Because we requested an RPC PING at transport creation time,
189 * this works only if the user space portmapper is rpcbind, and
190 * it's listening on AF_LOCAL on the named socket.
191 */
192 clnt = rpc_create(&args);
193 if (IS_ERR(clnt)) {
194 dprintk("RPC: failed to create AF_LOCAL rpcbind "
195 "client (errno %ld).\n", PTR_ERR(clnt));
196 result = -PTR_ERR(clnt);
197 goto out;
198 }
199
200 clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
201 if (IS_ERR(clnt4)) {
202 dprintk("RPC: failed to bind second program to "
203 "rpcbind v4 client (errno %ld).\n",
204 PTR_ERR(clnt4));
205 clnt4 = NULL;
206 }
207
208 /* Protected by rpcb_create_local_mutex */
209 rpcb_local_clnt = clnt;
210 rpcb_local_clnt4 = clnt4;
166 211
167static DEFINE_MUTEX(rpcb_create_local_mutex); 212out:
213 return result;
214}
168 215
169/* 216/*
170 * Returns zero on success, otherwise a negative errno value 217 * Returns zero on success, otherwise a negative errno value
171 * is returned. 218 * is returned.
172 */ 219 */
173static int rpcb_create_local(void) 220static int rpcb_create_local_net(void)
174{ 221{
222 static const struct sockaddr_in rpcb_inaddr_loopback = {
223 .sin_family = AF_INET,
224 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
225 .sin_port = htons(RPCBIND_PORT),
226 };
175 struct rpc_create_args args = { 227 struct rpc_create_args args = {
176 .net = &init_net, 228 .net = &init_net,
177 .protocol = XPRT_TRANSPORT_TCP, 229 .protocol = XPRT_TRANSPORT_TCP,
@@ -186,13 +238,6 @@ static int rpcb_create_local(void)
186 struct rpc_clnt *clnt, *clnt4; 238 struct rpc_clnt *clnt, *clnt4;
187 int result = 0; 239 int result = 0;
188 240
189 if (rpcb_local_clnt)
190 return result;
191
192 mutex_lock(&rpcb_create_local_mutex);
193 if (rpcb_local_clnt)
194 goto out;
195
196 clnt = rpc_create(&args); 241 clnt = rpc_create(&args);
197 if (IS_ERR(clnt)) { 242 if (IS_ERR(clnt)) {
198 dprintk("RPC: failed to create local rpcbind " 243 dprintk("RPC: failed to create local rpcbind "
@@ -214,10 +259,34 @@ static int rpcb_create_local(void)
214 clnt4 = NULL; 259 clnt4 = NULL;
215 } 260 }
216 261
262 /* Protected by rpcb_create_local_mutex */
217 rpcb_local_clnt = clnt; 263 rpcb_local_clnt = clnt;
218 rpcb_local_clnt4 = clnt4; 264 rpcb_local_clnt4 = clnt4;
219 265
220out: 266out:
267 return result;
268}
269
270/*
271 * Returns zero on success, otherwise a negative errno value
272 * is returned.
273 */
274static int rpcb_create_local(void)
275{
276 static DEFINE_MUTEX(rpcb_create_local_mutex);
277 int result = 0;
278
279 if (rpcb_local_clnt)
280 return result;
281
282 mutex_lock(&rpcb_create_local_mutex);
283 if (rpcb_local_clnt)
284 goto out;
285
286 if (rpcb_create_local_unix() != 0)
287 result = rpcb_create_local_net();
288
289out:
221 mutex_unlock(&rpcb_create_local_mutex); 290 mutex_unlock(&rpcb_create_local_mutex);
222 return result; 291 return result;
223} 292}