diff options
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 119 |
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 | ||
120 | static struct rpc_procinfo rpcb_procedures2[]; | 81 | static struct rpc_procinfo rpcb_procedures2[]; |
@@ -128,19 +89,6 @@ struct rpcb_info { | |||
128 | static struct rpcb_info rpcb_next_version[]; | 89 | static struct rpcb_info rpcb_next_version[]; |
129 | static struct rpcb_info rpcb_next_version6[]; | 90 | static struct rpcb_info rpcb_next_version6[]; |
130 | 91 | ||
131 | static 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 | |||
144 | static void rpcb_map_release(void *data) | 92 | static 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 | ||
152 | static const struct rpc_call_ops rpcb_getport_ops = { | 100 | static 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 | ||
164 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | 111 | static 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 | */ |
260 | int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, | 211 | int 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 | } |
296 | EXPORT_SYMBOL_GPL(rpcb_getport_sync); | 245 | EXPORT_SYMBOL_GPL(rpcb_getport_sync); |
297 | 246 | ||
247 | static 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); | |||
305 | void rpcb_getport_async(struct rpc_task *task) | 272 | void 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+ \ |