aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r--net/sunrpc/clnt.c88
1 files changed, 45 insertions, 43 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index e9735089bd66..803e93105af1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -79,7 +79,8 @@ static void call_connect_status(struct rpc_task *task);
79 79
80static int rpc_encode_header(struct rpc_task *task, 80static int rpc_encode_header(struct rpc_task *task,
81 struct xdr_stream *xdr); 81 struct xdr_stream *xdr);
82static __be32 *rpc_decode_header(struct rpc_task *task); 82static int rpc_decode_header(struct rpc_task *task,
83 struct xdr_stream *xdr);
83static int rpc_ping(struct rpc_clnt *clnt); 84static int rpc_ping(struct rpc_clnt *clnt);
84 85
85static void rpc_register_client(struct rpc_clnt *clnt) 86static void rpc_register_client(struct rpc_clnt *clnt)
@@ -2251,12 +2252,11 @@ call_decode(struct rpc_task *task)
2251{ 2252{
2252 struct rpc_clnt *clnt = task->tk_client; 2253 struct rpc_clnt *clnt = task->tk_client;
2253 struct rpc_rqst *req = task->tk_rqstp; 2254 struct rpc_rqst *req = task->tk_rqstp;
2254 kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; 2255 struct xdr_stream xdr;
2255 __be32 *p;
2256 2256
2257 dprint_status(task); 2257 dprint_status(task);
2258 2258
2259 if (!decode) { 2259 if (!task->tk_msg.rpc_proc->p_decode) {
2260 task->tk_action = rpc_exit_task; 2260 task->tk_action = rpc_exit_task;
2261 return; 2261 return;
2262 } 2262 }
@@ -2292,29 +2292,27 @@ call_decode(struct rpc_task *task)
2292 goto out_retry; 2292 goto out_retry;
2293 } 2293 }
2294 2294
2295 p = rpc_decode_header(task); 2295 xdr_init_decode(&xdr, &req->rq_rcv_buf,
2296 if (IS_ERR(p)) { 2296 req->rq_rcv_buf.head[0].iov_base, req);
2297 if (p == ERR_PTR(-EAGAIN)) 2297 switch (rpc_decode_header(task, &xdr)) {
2298 goto out_retry; 2298 case 0:
2299 task->tk_action = rpc_exit_task;
2300 task->tk_status = rpcauth_unwrap_resp(task, &xdr);
2301 dprintk("RPC: %5u %s result %d\n",
2302 task->tk_pid, __func__, task->tk_status);
2299 return; 2303 return;
2300 } 2304 case -EAGAIN:
2301 task->tk_action = rpc_exit_task;
2302
2303 task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
2304 task->tk_msg.rpc_resp);
2305
2306 dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
2307 task->tk_status);
2308 return;
2309out_retry: 2305out_retry:
2310 task->tk_status = 0; 2306 task->tk_status = 0;
2311 /* Note: rpc_decode_header() may have freed the RPC slot */ 2307 /* Note: rpc_decode_header() may have freed the RPC slot */
2312 if (task->tk_rqstp == req) { 2308 if (task->tk_rqstp == req) {
2313 xdr_free_bvec(&req->rq_rcv_buf); 2309 xdr_free_bvec(&req->rq_rcv_buf);
2314 req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; 2310 req->rq_reply_bytes_recvd = 0;
2315 if (task->tk_client->cl_discrtry) 2311 req->rq_rcv_buf.len = 0;
2316 xprt_conditional_disconnect(req->rq_xprt, 2312 if (task->tk_client->cl_discrtry)
2317 req->rq_connect_cookie); 2313 xprt_conditional_disconnect(req->rq_xprt,
2314 req->rq_connect_cookie);
2315 }
2318 } 2316 }
2319} 2317}
2320 2318
@@ -2347,14 +2345,12 @@ out_fail:
2347 return error; 2345 return error;
2348} 2346}
2349 2347
2350static noinline __be32 * 2348static noinline int
2351rpc_decode_header(struct rpc_task *task) 2349rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2352{ 2350{
2353 struct rpc_clnt *clnt = task->tk_client; 2351 struct rpc_clnt *clnt = task->tk_client;
2354 struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
2355 int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
2356 __be32 *p = iov->iov_base;
2357 int error = -EACCES; 2352 int error = -EACCES;
2353 __be32 *p;
2358 2354
2359 /* RFC-1014 says that the representation of XDR data must be a 2355 /* RFC-1014 says that the representation of XDR data must be a
2360 * multiple of four bytes 2356 * multiple of four bytes
@@ -2363,25 +2359,26 @@ rpc_decode_header(struct rpc_task *task)
2363 */ 2359 */
2364 if (task->tk_rqstp->rq_rcv_buf.len & 3) 2360 if (task->tk_rqstp->rq_rcv_buf.len & 3)
2365 goto out_badlen; 2361 goto out_badlen;
2366 if ((len -= 3) < 0)
2367 goto out_unparsable;
2368 2362
2363 p = xdr_inline_decode(xdr, 3 * sizeof(*p));
2364 if (!p)
2365 goto out_unparsable;
2369 p++; /* skip XID */ 2366 p++; /* skip XID */
2370 if (*p++ != rpc_reply) 2367 if (*p++ != rpc_reply)
2371 goto out_unparsable; 2368 goto out_unparsable;
2372 if (*p++ != rpc_msg_accepted) 2369 if (*p++ != rpc_msg_accepted)
2373 goto out_msg_denied; 2370 goto out_msg_denied;
2374 2371
2375 p = rpcauth_checkverf(task, p); 2372 error = rpcauth_checkverf(task, xdr);
2376 if (IS_ERR(p)) 2373 if (error)
2377 goto out_verifier; 2374 goto out_verifier;
2378 2375
2379 len = p - (__be32 *)iov->iov_base - 1; 2376 p = xdr_inline_decode(xdr, sizeof(*p));
2380 if (len < 0) 2377 if (!p)
2381 goto out_unparsable; 2378 goto out_unparsable;
2382 switch (*p++) { 2379 switch (*p) {
2383 case rpc_success: 2380 case rpc_success:
2384 return p; 2381 return 0;
2385 case rpc_prog_unavail: 2382 case rpc_prog_unavail:
2386 trace_rpc__prog_unavail(task); 2383 trace_rpc__prog_unavail(task);
2387 error = -EPFNOSUPPORT; 2384 error = -EPFNOSUPPORT;
@@ -2406,11 +2403,11 @@ out_garbage:
2406 if (task->tk_garb_retry) { 2403 if (task->tk_garb_retry) {
2407 task->tk_garb_retry--; 2404 task->tk_garb_retry--;
2408 task->tk_action = call_encode; 2405 task->tk_action = call_encode;
2409 return ERR_PTR(-EAGAIN); 2406 return -EAGAIN;
2410 } 2407 }
2411out_err: 2408out_err:
2412 rpc_exit(task, error); 2409 rpc_exit(task, error);
2413 return ERR_PTR(error); 2410 return error;
2414 2411
2415out_badlen: 2412out_badlen:
2416 trace_rpc__unparsable(task); 2413 trace_rpc__unparsable(task);
@@ -2424,10 +2421,12 @@ out_unparsable:
2424 2421
2425out_verifier: 2422out_verifier:
2426 trace_rpc_bad_verifier(task); 2423 trace_rpc_bad_verifier(task);
2427 error = PTR_ERR(p);
2428 goto out_garbage; 2424 goto out_garbage;
2429 2425
2430out_msg_denied: 2426out_msg_denied:
2427 p = xdr_inline_decode(xdr, sizeof(*p));
2428 if (!p)
2429 goto out_unparsable;
2431 switch (*p++) { 2430 switch (*p++) {
2432 case rpc_auth_error: 2431 case rpc_auth_error:
2433 break; 2432 break;
@@ -2441,6 +2440,9 @@ out_msg_denied:
2441 goto out_err; 2440 goto out_err;
2442 } 2441 }
2443 2442
2443 p = xdr_inline_decode(xdr, sizeof(*p));
2444 if (!p)
2445 goto out_unparsable;
2444 switch (*p++) { 2446 switch (*p++) {
2445 case rpc_autherr_rejectedcred: 2447 case rpc_autherr_rejectedcred:
2446 case rpc_autherr_rejectedverf: 2448 case rpc_autherr_rejectedverf:
@@ -2454,7 +2456,7 @@ out_msg_denied:
2454 /* Ensure we obtain a new XID! */ 2456 /* Ensure we obtain a new XID! */
2455 xprt_release(task); 2457 xprt_release(task);
2456 task->tk_action = call_reserve; 2458 task->tk_action = call_reserve;
2457 return ERR_PTR(-EAGAIN); 2459 return -EAGAIN;
2458 case rpc_autherr_badcred: 2460 case rpc_autherr_badcred:
2459 case rpc_autherr_badverf: 2461 case rpc_autherr_badverf:
2460 /* possibly garbled cred/verf? */ 2462 /* possibly garbled cred/verf? */
@@ -2463,7 +2465,7 @@ out_msg_denied:
2463 task->tk_garb_retry--; 2465 task->tk_garb_retry--;
2464 trace_rpc__bad_creds(task); 2466 trace_rpc__bad_creds(task);
2465 task->tk_action = call_encode; 2467 task->tk_action = call_encode;
2466 return ERR_PTR(-EAGAIN); 2468 return -EAGAIN;
2467 case rpc_autherr_tooweak: 2469 case rpc_autherr_tooweak:
2468 trace_rpc__auth_tooweak(task); 2470 trace_rpc__auth_tooweak(task);
2469 pr_warn("RPC: server %s requires stronger authentication.\n", 2471 pr_warn("RPC: server %s requires stronger authentication.\n",