summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@fys.uio.no>2003-01-12 21:41:07 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2003-01-12 21:41:07 -0800
commit6d52fdcbcd3ad58fef0cdef7ce4fccde01fc14c1 (patch)
tree949e36f233bf5485d0301c6d68f0825f90001e6a
parent756a93f720ecf1f695691e06712be128bad02be0 (diff)
[PATCH] XDR 'encode' phase move [2/6]
The RPCSEC_GSS user context defines a 'sequence number' in the AUTH header fields in order to provide protection against replay attacks. This number needs to lie within a given 'window', and is required to be updated even when retransmitting dropped requests. In order to allow this update to occur, move the XDR 'encode' phase so that it is done immediately before writing the data to the socket.
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--net/sunrpc/clnt.c24
-rw-r--r--net/sunrpc/xprt.c46
3 files changed, 39 insertions, 32 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 034aa2ac05e9..5e01355e19f6 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -187,6 +187,7 @@ void xprt_set_timeout(struct rpc_timeout *, unsigned int,
unsigned long);
void xprt_reserve(struct rpc_task *);
+int xprt_prepare_transmit(struct rpc_task *);
void xprt_transmit(struct rpc_task *);
void xprt_receive(struct rpc_task *);
int xprt_adjust_timeout(struct rpc_timeout *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 569e860d27ed..3a93fffc9056 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -470,7 +470,7 @@ call_allocate(struct rpc_task *task)
dprintk("RPC: %4d call_allocate (status %d)\n",
task->tk_pid, task->tk_status);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
if (task->tk_buffer)
return;
@@ -510,8 +510,6 @@ call_encode(struct rpc_task *task)
dprintk("RPC: %4d call_encode (status %d)\n",
task->tk_pid, task->tk_status);
- task->tk_action = call_bind;
-
/* Default buffer setup */
bufsiz = task->tk_bufsize >> 1;
sndbuf->head[0].iov_base = (void *)task->tk_buffer;
@@ -533,7 +531,8 @@ call_encode(struct rpc_task *task)
if (!(p = call_header(task))) {
printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
rpc_exit(task, -EIO);
- } else
+ return;
+ }
if (encode && (status = encode(req, p, task->tk_msg.rpc_argp)) < 0) {
printk(KERN_WARNING "%s: can't encode arguments: %d\n",
clnt->cl_protname, -status);
@@ -617,8 +616,17 @@ call_transmit(struct rpc_task *task)
task->tk_action = call_status;
if (task->tk_status < 0)
return;
+ task->tk_status = xprt_prepare_transmit(task);
+ if (task->tk_status < 0)
+ return;
+ /* Encode here so that rpcsec_gss can use correct sequence number. */
+ call_encode(task);
+ if (task->tk_status < 0)
+ return;
xprt_transmit(task);
- if (!task->tk_msg.rpc_proc->p_decode && task->tk_status >= 0) {
+ if (task->tk_status < 0)
+ return;
+ if (!task->tk_msg.rpc_proc->p_decode) {
task->tk_action = NULL;
rpc_wake_up_task(task);
}
@@ -758,7 +766,7 @@ call_decode(struct rpc_task *task)
if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
task->tk_flags ^= RPC_CALL_REALUID;
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
task->tk_suid_retry--;
return;
}
@@ -864,7 +872,7 @@ call_verify(struct rpc_task *task)
task->tk_garb_retry--;
dprintk("RPC: %4d call_verify: retry garbled creds\n",
task->tk_pid);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
return NULL;
case RPC_AUTH_TOOWEAK:
printk(KERN_NOTICE "call_verify: server requires stronger "
@@ -899,7 +907,7 @@ garbage:
if (task->tk_garb_retry) {
task->tk_garb_retry--;
dprintk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
return NULL;
}
printk(KERN_WARNING "RPC: garbage, exit EIO\n");
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index f2630a93ef50..5ff838e376c2 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -83,7 +83,6 @@
* Local functions
*/
static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);
-static void do_xprt_transmit(struct rpc_task *);
static inline void do_xprt_reserve(struct rpc_task *);
static void xprt_disconnect(struct rpc_xprt *);
static void xprt_conn_status(struct rpc_task *task);
@@ -1091,51 +1090,40 @@ out_unlock:
* Place the actual RPC call.
* We have to copy the iovec because sendmsg fiddles with its contents.
*/
-void
-xprt_transmit(struct rpc_task *task)
+int
+xprt_prepare_transmit(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
+ int err = 0;
- dprintk("RPC: %4d xprt_transmit(%x)\n", task->tk_pid,
- *(u32 *)(req->rq_svec[0].iov_base));
+ dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid);
if (xprt->shutdown)
- task->tk_status = -EIO;
+ return -EIO;
if (!xprt_connected(xprt))
- task->tk_status = -ENOTCONN;
-
- if (task->tk_status < 0)
- return;
+ return -ENOTCONN;
if (task->tk_rpcwait)
rpc_remove_wait_queue(task);
- /* set up everything as needed. */
- /* Write the record marker */
- if (xprt->stream) {
- u32 *marker = req->rq_svec[0].iov_base;
-
- *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
- }
-
spin_lock_bh(&xprt->sock_lock);
if (!__xprt_lock_write(xprt, task)) {
- spin_unlock_bh(&xprt->sock_lock);
- return;
+ err = -EAGAIN;
+ goto out_unlock;
}
if (list_empty(&req->rq_list)) {
list_add_tail(&req->rq_list, &xprt->recv);
req->rq_received = 0;
}
+out_unlock:
spin_unlock_bh(&xprt->sock_lock);
-
- do_xprt_transmit(task);
+ return err;
}
-static void
-do_xprt_transmit(struct rpc_task *task)
+void
+xprt_transmit(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp;
@@ -1143,6 +1131,16 @@ do_xprt_transmit(struct rpc_task *task)
int status, retry = 0;
+ dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
+
+ /* set up everything as needed. */
+ /* Write the record marker */
+ if (xprt->stream) {
+ u32 *marker = req->rq_svec[0].iov_base;
+
+ *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+ }
+
/* Continue transmitting the packet/record. We must be careful
* to cope with writespace callbacks arriving _after_ we have
* called xprt_sendmsg().