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.c105
1 files changed, 82 insertions, 23 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 830faf4d9997..121105355f60 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -20,6 +20,8 @@
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>
24#include <linux/slab.h>
23#include <net/ipv6.h> 25#include <net/ipv6.h>
24 26
25#include <linux/sunrpc/clnt.h> 27#include <linux/sunrpc/clnt.h>
@@ -110,6 +112,9 @@ static void rpcb_getport_done(struct rpc_task *, void *);
110static void rpcb_map_release(void *data); 112static void rpcb_map_release(void *data);
111static struct rpc_program rpcb_program; 113static struct rpc_program rpcb_program;
112 114
115static struct rpc_clnt * rpcb_local_clnt;
116static struct rpc_clnt * rpcb_local_clnt4;
117
113struct rpcbind_args { 118struct rpcbind_args {
114 struct rpc_xprt * r_xprt; 119 struct rpc_xprt * r_xprt;
115 120
@@ -163,21 +168,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
163 .sin_port = htons(RPCBIND_PORT), 168 .sin_port = htons(RPCBIND_PORT),
164}; 169};
165 170
166static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, 171static DEFINE_MUTEX(rpcb_create_local_mutex);
167 size_t addrlen, u32 version) 172
173/*
174 * Returns zero on success, otherwise a negative errno value
175 * is returned.
176 */
177static int rpcb_create_local(void)
168{ 178{
169 struct rpc_create_args args = { 179 struct rpc_create_args args = {
170 .protocol = XPRT_TRANSPORT_UDP, 180 .protocol = XPRT_TRANSPORT_TCP,
171 .address = addr, 181 .address = (struct sockaddr *)&rpcb_inaddr_loopback,
172 .addrsize = addrlen, 182 .addrsize = sizeof(rpcb_inaddr_loopback),
173 .servername = "localhost", 183 .servername = "localhost",
174 .program = &rpcb_program, 184 .program = &rpcb_program,
175 .version = version, 185 .version = RPCBVERS_2,
176 .authflavor = RPC_AUTH_UNIX, 186 .authflavor = RPC_AUTH_UNIX,
177 .flags = RPC_CLNT_CREATE_NOPING, 187 .flags = RPC_CLNT_CREATE_NOPING,
178 }; 188 };
189 struct rpc_clnt *clnt, *clnt4;
190 int result = 0;
191
192 if (rpcb_local_clnt)
193 return result;
194
195 mutex_lock(&rpcb_create_local_mutex);
196 if (rpcb_local_clnt)
197 goto out;
198
199 clnt = rpc_create(&args);
200 if (IS_ERR(clnt)) {
201 dprintk("RPC: failed to create local rpcbind "
202 "client (errno %ld).\n", PTR_ERR(clnt));
203 result = -PTR_ERR(clnt);
204 goto out;
205 }
179 206
180 return rpc_create(&args); 207 /*
208 * This results in an RPC ping. On systems running portmapper,
209 * the v4 ping will fail. Proceed anyway, but disallow rpcb
210 * v4 upcalls.
211 */
212 clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
213 if (IS_ERR(clnt4)) {
214 dprintk("RPC: failed to create local rpcbind v4 "
215 "cleint (errno %ld).\n", PTR_ERR(clnt4));
216 clnt4 = NULL;
217 }
218
219 rpcb_local_clnt = clnt;
220 rpcb_local_clnt4 = clnt4;
221
222out:
223 mutex_unlock(&rpcb_create_local_mutex);
224 return result;
181} 225}
182 226
183static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, 227static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
@@ -209,22 +253,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
209 return rpc_create(&args); 253 return rpc_create(&args);
210} 254}
211 255
212static int rpcb_register_call(const u32 version, struct rpc_message *msg) 256static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
213{ 257{
214 struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback;
215 size_t addrlen = sizeof(rpcb_inaddr_loopback);
216 struct rpc_clnt *rpcb_clnt;
217 int result, error = 0; 258 int result, error = 0;
218 259
219 msg->rpc_resp = &result; 260 msg->rpc_resp = &result;
220 261
221 rpcb_clnt = rpcb_create_local(addr, addrlen, version); 262 error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
222 if (!IS_ERR(rpcb_clnt)) {
223 error = rpc_call_sync(rpcb_clnt, msg, 0);
224 rpc_shutdown_client(rpcb_clnt);
225 } else
226 error = PTR_ERR(rpcb_clnt);
227
228 if (error < 0) { 263 if (error < 0) {
229 dprintk("RPC: failed to contact local rpcbind " 264 dprintk("RPC: failed to contact local rpcbind "
230 "server (errno %d).\n", -error); 265 "server (errno %d).\n", -error);
@@ -279,6 +314,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
279 struct rpc_message msg = { 314 struct rpc_message msg = {
280 .rpc_argp = &map, 315 .rpc_argp = &map,
281 }; 316 };
317 int error;
318
319 error = rpcb_create_local();
320 if (error)
321 return error;
282 322
283 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " 323 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
284 "rpcbind\n", (port ? "" : "un"), 324 "rpcbind\n", (port ? "" : "un"),
@@ -288,7 +328,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
288 if (port) 328 if (port)
289 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; 329 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
290 330
291 return rpcb_register_call(RPCBVERS_2, &msg); 331 return rpcb_register_call(rpcb_local_clnt, &msg);
292} 332}
293 333
294/* 334/*
@@ -313,7 +353,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
313 if (port) 353 if (port)
314 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 354 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
315 355
316 result = rpcb_register_call(RPCBVERS_4, msg); 356 result = rpcb_register_call(rpcb_local_clnt4, msg);
317 kfree(map->r_addr); 357 kfree(map->r_addr);
318 return result; 358 return result;
319} 359}
@@ -340,7 +380,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
340 if (port) 380 if (port)
341 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 381 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
342 382
343 result = rpcb_register_call(RPCBVERS_4, msg); 383 result = rpcb_register_call(rpcb_local_clnt4, msg);
344 kfree(map->r_addr); 384 kfree(map->r_addr);
345 return result; 385 return result;
346} 386}
@@ -356,7 +396,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
356 map->r_addr = ""; 396 map->r_addr = "";
357 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; 397 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
358 398
359 return rpcb_register_call(RPCBVERS_4, msg); 399 return rpcb_register_call(rpcb_local_clnt4, msg);
360} 400}
361 401
362/** 402/**
@@ -414,6 +454,13 @@ int rpcb_v4_register(const u32 program, const u32 version,
414 struct rpc_message msg = { 454 struct rpc_message msg = {
415 .rpc_argp = &map, 455 .rpc_argp = &map,
416 }; 456 };
457 int error;
458
459 error = rpcb_create_local();
460 if (error)
461 return error;
462 if (rpcb_local_clnt4 == NULL)
463 return -EPROTONOSUPPORT;
417 464
418 if (address == NULL) 465 if (address == NULL)
419 return rpcb_unregister_all_protofamilies(&msg); 466 return rpcb_unregister_all_protofamilies(&msg);
@@ -491,7 +538,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
491 .rpc_message = &msg, 538 .rpc_message = &msg,
492 .callback_ops = &rpcb_getport_ops, 539 .callback_ops = &rpcb_getport_ops,
493 .callback_data = map, 540 .callback_data = map,
494 .flags = RPC_TASK_ASYNC, 541 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN,
495 }; 542 };
496 543
497 return rpc_run_task(&task_setup_data); 544 return rpc_run_task(&task_setup_data);
@@ -1027,3 +1074,15 @@ static struct rpc_program rpcb_program = {
1027 .version = rpcb_version, 1074 .version = rpcb_version,
1028 .stats = &rpcb_stats, 1075 .stats = &rpcb_stats,
1029}; 1076};
1077
1078/**
1079 * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
1080 *
1081 */
1082void cleanup_rpcb_clnt(void)
1083{
1084 if (rpcb_local_clnt4)
1085 rpc_shutdown_client(rpcb_local_clnt4);
1086 if (rpcb_local_clnt)
1087 rpc_shutdown_client(rpcb_local_clnt);
1088}