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.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 28f50da60ceb..116db74dd942 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -20,6 +20,7 @@
20#include <linux/in6.h> 20#include <linux/in6.h>
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/mutex.h>
23#include <net/ipv6.h> 24#include <net/ipv6.h>
24 25
25#include <linux/sunrpc/clnt.h> 26#include <linux/sunrpc/clnt.h>
@@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *);
110static void rpcb_map_release(void *data); 111static void rpcb_map_release(void *data);
111static struct rpc_program rpcb_program; 112static struct rpc_program rpcb_program;
112 113
114static struct rpc_clnt * rpcb_local_clnt;
115static struct rpc_clnt * rpcb_local_clnt4;
116
113struct rpcbind_args { 117struct rpcbind_args {
114 struct rpc_xprt * r_xprt; 118 struct rpc_xprt * r_xprt;
115 119
@@ -163,7 +167,13 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
163 .sin_port = htons(RPCBIND_PORT), 167 .sin_port = htons(RPCBIND_PORT),
164}; 168};
165 169
166static struct rpc_clnt *rpcb_create_local(u32 version) 170static DEFINE_MUTEX(rpcb_create_local_mutex);
171
172/*
173 * Returns zero on success, otherwise a negative errno value
174 * is returned.
175 */
176static int rpcb_create_local(void)
167{ 177{
168 struct rpc_create_args args = { 178 struct rpc_create_args args = {
169 .protocol = XPRT_TRANSPORT_UDP, 179 .protocol = XPRT_TRANSPORT_UDP,
@@ -171,12 +181,46 @@ static struct rpc_clnt *rpcb_create_local(u32 version)
171 .addrsize = sizeof(rpcb_inaddr_loopback), 181 .addrsize = sizeof(rpcb_inaddr_loopback),
172 .servername = "localhost", 182 .servername = "localhost",
173 .program = &rpcb_program, 183 .program = &rpcb_program,
174 .version = version, 184 .version = RPCBVERS_2,
175 .authflavor = RPC_AUTH_UNIX, 185 .authflavor = RPC_AUTH_UNIX,
176 .flags = RPC_CLNT_CREATE_NOPING, 186 .flags = RPC_CLNT_CREATE_NOPING,
177 }; 187 };
188 struct rpc_clnt *clnt, *clnt4;
189 int result = 0;
190
191 if (rpcb_local_clnt)
192 return result;
193
194 mutex_lock(&rpcb_create_local_mutex);
195 if (rpcb_local_clnt)
196 goto out;
197
198 clnt = rpc_create(&args);
199 if (IS_ERR(clnt)) {
200 dprintk("RPC: failed to create local rpcbind "
201 "client (errno %ld).\n", PTR_ERR(clnt));
202 result = -PTR_ERR(clnt);
203 goto out;
204 }
178 205
179 return rpc_create(&args); 206 /*
207 * This results in an RPC ping. On systems running portmapper,
208 * the v4 ping will fail. Proceed anyway, but disallow rpcb
209 * v4 upcalls.
210 */
211 clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
212 if (IS_ERR(clnt4)) {
213 dprintk("RPC: failed to create local rpcbind v4 "
214 "cleint (errno %ld).\n", PTR_ERR(clnt4));
215 clnt4 = NULL;
216 }
217
218 rpcb_local_clnt = clnt;
219 rpcb_local_clnt4 = clnt4;
220
221out:
222 mutex_unlock(&rpcb_create_local_mutex);
223 return result;
180} 224}
181 225
182static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, 226static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
@@ -208,20 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
208 return rpc_create(&args); 252 return rpc_create(&args);
209} 253}
210 254
211static int rpcb_register_call(const u32 version, struct rpc_message *msg) 255static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
212{ 256{
213 struct rpc_clnt *rpcb_clnt;
214 int result, error = 0; 257 int result, error = 0;
215 258
216 msg->rpc_resp = &result; 259 msg->rpc_resp = &result;
217 260
218 rpcb_clnt = rpcb_create_local(version); 261 error = rpc_call_sync(clnt, msg, 0);
219 if (!IS_ERR(rpcb_clnt)) {
220 error = rpc_call_sync(rpcb_clnt, msg, 0);
221 rpc_shutdown_client(rpcb_clnt);
222 } else
223 error = PTR_ERR(rpcb_clnt);
224
225 if (error < 0) { 262 if (error < 0) {
226 dprintk("RPC: failed to contact local rpcbind " 263 dprintk("RPC: failed to contact local rpcbind "
227 "server (errno %d).\n", -error); 264 "server (errno %d).\n", -error);
@@ -276,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
276 struct rpc_message msg = { 313 struct rpc_message msg = {
277 .rpc_argp = &map, 314 .rpc_argp = &map,
278 }; 315 };
316 int error;
317
318 error = rpcb_create_local();
319 if (error)
320 return error;
279 321
280 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " 322 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
281 "rpcbind\n", (port ? "" : "un"), 323 "rpcbind\n", (port ? "" : "un"),
@@ -285,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
285 if (port) 327 if (port)
286 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; 328 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
287 329
288 return rpcb_register_call(RPCBVERS_2, &msg); 330 return rpcb_register_call(rpcb_local_clnt, &msg);
289} 331}
290 332
291/* 333/*
@@ -310,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
310 if (port) 352 if (port)
311 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 353 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
312 354
313 result = rpcb_register_call(RPCBVERS_4, msg); 355 result = rpcb_register_call(rpcb_local_clnt4, msg);
314 kfree(map->r_addr); 356 kfree(map->r_addr);
315 return result; 357 return result;
316} 358}
@@ -337,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
337 if (port) 379 if (port)
338 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 380 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
339 381
340 result = rpcb_register_call(RPCBVERS_4, msg); 382 result = rpcb_register_call(rpcb_local_clnt4, msg);
341 kfree(map->r_addr); 383 kfree(map->r_addr);
342 return result; 384 return result;
343} 385}
@@ -353,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
353 map->r_addr = ""; 395 map->r_addr = "";
354 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; 396 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
355 397
356 return rpcb_register_call(RPCBVERS_4, msg); 398 return rpcb_register_call(rpcb_local_clnt4, msg);
357} 399}
358 400
359/** 401/**
@@ -411,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version,
411 struct rpc_message msg = { 453 struct rpc_message msg = {
412 .rpc_argp = &map, 454 .rpc_argp = &map,
413 }; 455 };
456 int error;
457
458 error = rpcb_create_local();
459 if (error)
460 return error;
461 if (rpcb_local_clnt4 == NULL)
462 return -EPROTONOSUPPORT;
414 463
415 if (address == NULL) 464 if (address == NULL)
416 return rpcb_unregister_all_protofamilies(&msg); 465 return rpcb_unregister_all_protofamilies(&msg);
@@ -1024,3 +1073,15 @@ static struct rpc_program rpcb_program = {
1024 .version = rpcb_version, 1073 .version = rpcb_version,
1025 .stats = &rpcb_stats, 1074 .stats = &rpcb_stats,
1026}; 1075};
1076
1077/**
1078 * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
1079 *
1080 */
1081void cleanup_rpcb_clnt(void)
1082{
1083 if (rpcb_local_clnt4)
1084 rpc_shutdown_client(rpcb_local_clnt4);
1085 if (rpcb_local_clnt)
1086 rpc_shutdown_client(rpcb_local_clnt);
1087}