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.c119
1 files changed, 43 insertions, 76 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index a05493aedb68..fa5b8f202d5b 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -55,45 +55,6 @@ enum {
55#define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT 55#define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT
56 56
57/* 57/*
58 * r_addr
59 *
60 * Quoting RFC 3530, section 2.2:
61 *
62 * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
63 * US-ASCII string:
64 *
65 * h1.h2.h3.h4.p1.p2
66 *
67 * The prefix, "h1.h2.h3.h4", is the standard textual form for
68 * representing an IPv4 address, which is always four octets long.
69 * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
70 * the first through fourth octets each converted to ASCII-decimal.
71 * Assuming big-endian ordering, p1 and p2 are, respectively, the first
72 * and second octets each converted to ASCII-decimal. For example, if a
73 * host, in big-endian order, has an address of 0x0A010307 and there is
74 * a service listening on, in big endian order, port 0x020F (decimal
75 * 527), then the complete universal address is "10.1.3.7.2.15".
76 *
77 * ...
78 *
79 * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
80 * US-ASCII string:
81 *
82 * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
83 *
84 * The suffix "p1.p2" is the service port, and is computed the same way
85 * as with universal addresses for TCP and UDP over IPv4. The prefix,
86 * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
87 * representing an IPv6 address as defined in Section 2.2 of [RFC2373].
88 * Additionally, the two alternative forms specified in Section 2.2 of
89 * [RFC2373] are also acceptable.
90 *
91 * XXX: Currently this implementation does not explicitly convert the
92 * stored address to US-ASCII on non-ASCII systems.
93 */
94#define RPCB_MAXADDRLEN (128u)
95
96/*
97 * r_owner 58 * r_owner
98 * 59 *
99 * The "owner" is allowed to unset a service in the rpcbind database. 60 * The "owner" is allowed to unset a service in the rpcbind database.
@@ -112,9 +73,9 @@ struct rpcbind_args {
112 u32 r_vers; 73 u32 r_vers;
113 u32 r_prot; 74 u32 r_prot;
114 unsigned short r_port; 75 unsigned short r_port;
115 char * r_netid; 76 const char * r_netid;
116 char r_addr[RPCB_MAXADDRLEN]; 77 const char * r_addr;
117 char * r_owner; 78 const char * r_owner;
118}; 79};
119 80
120static struct rpc_procinfo rpcb_procedures2[]; 81static struct rpc_procinfo rpcb_procedures2[];
@@ -128,19 +89,6 @@ struct rpcb_info {
128static struct rpcb_info rpcb_next_version[]; 89static struct rpcb_info rpcb_next_version[];
129static struct rpcb_info rpcb_next_version6[]; 90static struct rpcb_info rpcb_next_version6[];
130 91
131static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
132{
133 struct rpcbind_args *map = calldata;
134 struct rpc_xprt *xprt = map->r_xprt;
135 struct rpc_message msg = {
136 .rpc_proc = rpcb_next_version[xprt->bind_index].rpc_proc,
137 .rpc_argp = map,
138 .rpc_resp = &map->r_port,
139 };
140
141 rpc_call_setup(task, &msg, 0);
142}
143
144static void rpcb_map_release(void *data) 92static void rpcb_map_release(void *data)
145{ 93{
146 struct rpcbind_args *map = data; 94 struct rpcbind_args *map = data;
@@ -150,7 +98,6 @@ static void rpcb_map_release(void *data)
150} 98}
151 99
152static const struct rpc_call_ops rpcb_getport_ops = { 100static const struct rpc_call_ops rpcb_getport_ops = {
153 .rpc_call_prepare = rpcb_getport_prepare,
154 .rpc_call_done = rpcb_getport_done, 101 .rpc_call_done = rpcb_getport_done,
155 .rpc_release = rpcb_map_release, 102 .rpc_release = rpcb_map_release,
156}; 103};
@@ -162,12 +109,13 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
162} 109}
163 110
164static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, 111static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
165 int proto, int version, int privileged) 112 size_t salen, int proto, u32 version,
113 int privileged)
166{ 114{
167 struct rpc_create_args args = { 115 struct rpc_create_args args = {
168 .protocol = proto, 116 .protocol = proto,
169 .address = srvaddr, 117 .address = srvaddr,
170 .addrsize = sizeof(struct sockaddr_in), 118 .addrsize = salen,
171 .servername = hostname, 119 .servername = hostname,
172 .program = &rpcb_program, 120 .program = &rpcb_program,
173 .version = version, 121 .version = version,
@@ -230,7 +178,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
230 prog, vers, prot, port); 178 prog, vers, prot, port);
231 179
232 rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, 180 rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin,
233 XPRT_TRANSPORT_UDP, 2, 1); 181 sizeof(sin), XPRT_TRANSPORT_UDP, 2, 1);
234 if (IS_ERR(rpcb_clnt)) 182 if (IS_ERR(rpcb_clnt))
235 return PTR_ERR(rpcb_clnt); 183 return PTR_ERR(rpcb_clnt);
236 184
@@ -252,13 +200,15 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
252 * @vers: RPC version number to bind 200 * @vers: RPC version number to bind
253 * @prot: transport protocol to use to make this request 201 * @prot: transport protocol to use to make this request
254 * 202 *
203 * Return value is the requested advertised port number,
204 * or a negative errno value.
205 *
255 * Called from outside the RPC client in a synchronous task context. 206 * Called from outside the RPC client in a synchronous task context.
256 * Uses default timeout parameters specified by underlying transport. 207 * Uses default timeout parameters specified by underlying transport.
257 * 208 *
258 * XXX: Needs to support IPv6, and rpcbind versions 3 and 4 209 * XXX: Needs to support IPv6
259 */ 210 */
260int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, 211int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
261 __u32 vers, int prot)
262{ 212{
263 struct rpcbind_args map = { 213 struct rpcbind_args map = {
264 .r_prog = prog, 214 .r_prog = prog,
@@ -272,14 +222,13 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
272 .rpc_resp = &map.r_port, 222 .rpc_resp = &map.r_port,
273 }; 223 };
274 struct rpc_clnt *rpcb_clnt; 224 struct rpc_clnt *rpcb_clnt;
275 char hostname[40];
276 int status; 225 int status;
277 226
278 dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n", 227 dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
279 __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); 228 __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
280 229
281 sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); 230 rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
282 rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0); 231 sizeof(*sin), prot, 2, 0);
283 if (IS_ERR(rpcb_clnt)) 232 if (IS_ERR(rpcb_clnt))
284 return PTR_ERR(rpcb_clnt); 233 return PTR_ERR(rpcb_clnt);
285 234
@@ -295,6 +244,24 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
295} 244}
296EXPORT_SYMBOL_GPL(rpcb_getport_sync); 245EXPORT_SYMBOL_GPL(rpcb_getport_sync);
297 246
247static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version)
248{
249 struct rpc_message msg = {
250 .rpc_proc = rpcb_next_version[version].rpc_proc,
251 .rpc_argp = map,
252 .rpc_resp = &map->r_port,
253 };
254 struct rpc_task_setup task_setup_data = {
255 .rpc_client = rpcb_clnt,
256 .rpc_message = &msg,
257 .callback_ops = &rpcb_getport_ops,
258 .callback_data = map,
259 .flags = RPC_TASK_ASYNC,
260 };
261
262 return rpc_run_task(&task_setup_data);
263}
264
298/** 265/**
299 * rpcb_getport_async - obtain the port for a given RPC service on a given host 266 * rpcb_getport_async - obtain the port for a given RPC service on a given host
300 * @task: task that is waiting for portmapper request 267 * @task: task that is waiting for portmapper request
@@ -305,12 +272,14 @@ EXPORT_SYMBOL_GPL(rpcb_getport_sync);
305void rpcb_getport_async(struct rpc_task *task) 272void rpcb_getport_async(struct rpc_task *task)
306{ 273{
307 struct rpc_clnt *clnt = task->tk_client; 274 struct rpc_clnt *clnt = task->tk_client;
308 int bind_version; 275 u32 bind_version;
309 struct rpc_xprt *xprt = task->tk_xprt; 276 struct rpc_xprt *xprt = task->tk_xprt;
310 struct rpc_clnt *rpcb_clnt; 277 struct rpc_clnt *rpcb_clnt;
311 static struct rpcbind_args *map; 278 static struct rpcbind_args *map;
312 struct rpc_task *child; 279 struct rpc_task *child;
313 struct sockaddr addr; 280 struct sockaddr_storage addr;
281 struct sockaddr *sap = (struct sockaddr *)&addr;
282 size_t salen;
314 int status; 283 int status;
315 struct rpcb_info *info; 284 struct rpcb_info *info;
316 285
@@ -340,10 +309,10 @@ void rpcb_getport_async(struct rpc_task *task)
340 goto bailout_nofree; 309 goto bailout_nofree;
341 } 310 }
342 311
343 rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); 312 salen = rpc_peeraddr(clnt, sap, sizeof(addr));
344 313
345 /* Don't ever use rpcbind v2 for AF_INET6 requests */ 314 /* Don't ever use rpcbind v2 for AF_INET6 requests */
346 switch (addr.sa_family) { 315 switch (sap->sa_family) {
347 case AF_INET: 316 case AF_INET:
348 info = rpcb_next_version; 317 info = rpcb_next_version;
349 break; 318 break;
@@ -368,7 +337,7 @@ void rpcb_getport_async(struct rpc_task *task)
368 dprintk("RPC: %5u %s: trying rpcbind version %u\n", 337 dprintk("RPC: %5u %s: trying rpcbind version %u\n",
369 task->tk_pid, __FUNCTION__, bind_version); 338 task->tk_pid, __FUNCTION__, bind_version);
370 339
371 rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, 340 rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
372 bind_version, 0); 341 bind_version, 0);
373 if (IS_ERR(rpcb_clnt)) { 342 if (IS_ERR(rpcb_clnt)) {
374 status = PTR_ERR(rpcb_clnt); 343 status = PTR_ERR(rpcb_clnt);
@@ -390,12 +359,10 @@ void rpcb_getport_async(struct rpc_task *task)
390 map->r_port = 0; 359 map->r_port = 0;
391 map->r_xprt = xprt_get(xprt); 360 map->r_xprt = xprt_get(xprt);
392 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); 361 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID);
393 memcpy(map->r_addr, 362 map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
394 rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR),
395 sizeof(map->r_addr));
396 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ 363 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */
397 364
398 child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); 365 child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index);
399 rpc_release_client(rpcb_clnt); 366 rpc_release_client(rpcb_clnt);
400 if (IS_ERR(child)) { 367 if (IS_ERR(child)) {
401 status = -EIO; 368 status = -EIO;
@@ -518,7 +485,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
518 * Simple sanity check. The smallest possible universal 485 * Simple sanity check. The smallest possible universal
519 * address is an IPv4 address string containing 11 bytes. 486 * address is an IPv4 address string containing 11 bytes.
520 */ 487 */
521 if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) 488 if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN)
522 goto out_err; 489 goto out_err;
523 490
524 /* 491 /*
@@ -569,7 +536,7 @@ out_err:
569#define RPCB_boolean_sz (1u) 536#define RPCB_boolean_sz (1u)
570 537
571#define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) 538#define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN))
572#define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) 539#define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
573#define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) 540#define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN))
574 541
575#define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \ 542#define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \