]> git.hungrycats.org Git - linux/commitdiff
[PATCH] XDR 'encode' phase move [2/6]
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 13 Jan 2003 05:41:07 +0000 (21:41 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Mon, 13 Jan 2003 05:41:07 +0000 (21:41 -0800)
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.

include/linux/sunrpc/xprt.h
net/sunrpc/clnt.c
net/sunrpc/xprt.c

index 034aa2ac05e9c4b5cfe9f921d6d0de1486d391fb..5e01355e19f67311071c76279b500b47819ebf82 100644 (file)
@@ -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 *);
index 569e860d27edf80e40d085fb95cd39b83d10f8f5..3a93fffc9056a3f5bb51b7fbfb8832802ba510f4 100644 (file)
@@ -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);
@@ -615,10 +614,19 @@ call_transmit(struct rpc_task *task)
                                task->tk_pid, task->tk_status);
 
        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");
index f2630a93ef5045ebd57b0464247eb629203671e9..5ff838e376c2df0750ffff1c00b3af053bf63758 100644 (file)
@@ -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().