r8021: we only need to return STATUS_BUFFER_OVERFLOW for the ipc_trans replies
authorStefan Metzmacher <metze@samba.org>
Thu, 30 Jun 2005 17:10:03 +0000 (17:10 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:19:00 +0000 (13:19 -0500)
and not for the ipc_read() replies as here the client explicit says how much data it wants

the write_fn() in dcesrv_output() now returns NTSTATUS

and the ipc specific implementations are moved to the ntvfs_ipc module

metze
(This used to be commit fe483dcd874b7243d61e9623840c672b4ea06b2c)

source4/ntvfs/ipc/vfs_ipc.c
source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcerpc_sock.c

index 68c59b75027a6cf08af8d4e299b0c06030f4036d..2c148fbd0cf8627097f9c51dfe652f2b4f333c18 100644 (file)
@@ -350,6 +350,18 @@ static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_ACCESS_DENIED;
 }
 
+static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+       DATA_BLOB *blob = private_data;
+
+       if (out->length < blob->length) {
+               blob->length = out->length;
+       }
+       memcpy(blob->data, out->data, blob->length);
+       *nwritten = blob->length;
+       return NT_STATUS_OK;
+}
+
 /*
   read from a file
 */
@@ -380,7 +392,7 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
        }
 
        if (data.length != 0) {
-               status = dcesrv_output_blob(p->dce_conn, &data);
+               status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
                if (NT_STATUS_IS_ERR(status)) {
                        return status;
                }
@@ -604,6 +616,22 @@ static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_ACCESS_DENIED;
 }
 
+static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       DATA_BLOB *blob = private_data;
+
+       if (out->length > blob->length) {
+               status = STATUS_BUFFER_OVERFLOW;
+       }
+
+       if (out->length < blob->length) {
+               blob->length = out->length;
+       }
+       memcpy(blob->data, out->data, blob->length);
+       *nwritten = blob->length;
+       return status;
+}
 
 /* SMBtrans - handle a DCERPC command */
 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
@@ -638,7 +666,7 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
          async calls. Again, we only expect NT_STATUS_OK. If the call fails then
          the error is encoded at the dcerpc level
        */
-       status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
+       status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
        if (NT_STATUS_IS_ERR(status)) {
                return status;
        }
index 87f8c9a42100e5b97ac7ae78bbb9b5e9893e274b..15da8c6964620240a0052aa5b761dde967254645 100644 (file)
@@ -1100,20 +1100,19 @@ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
 
   The first argument to write_fn() will be 'private', the second will
   be a pointer to a buffer containing the data to be sent and the 3rd
-  will be the number of bytes to be sent.
+  will be a pointer to a size_t variable that will be set to the
+  number of bytes that are consumed from the output.
 
-  write_fn() should return the number of bytes successfully written.
-
-  this will return STATUS_BUFFER_OVERFLOW if there is more to be written
   from the current fragment
 */
 NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, 
-                      void *private,
-                      ssize_t (*write_fn)(void *, DATA_BLOB *))
+                      void *private_data,
+                      NTSTATUS (*write_fn)(void *private_data, DATA_BLOB *output, size_t *nwritten))
 {
+       NTSTATUS status;
        struct dcesrv_call_state *call;
        struct dcesrv_call_reply *rep;
-       ssize_t nwritten;
+       size_t nwritten;
 
        call = dce_conn->call_list;
        if (!call || !call->replies) {
@@ -1128,12 +1127,8 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
        }
        rep = call->replies;
 
-       nwritten = write_fn(private, &rep->data);
-       if (nwritten == -1) {
-               /* TODO: hmm, how do we cope with this? destroy the
-                  connection perhaps? */
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+       status = write_fn(private_data, &rep->data, &nwritten);
+       NT_STATUS_IS_ERR_RETURN(status);
 
        rep->data.length -= nwritten;
        rep->data.data += nwritten;
@@ -1141,8 +1136,6 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
        if (rep->data.length == 0) {
                /* we're done with this section of the call */
                DLIST_REMOVE(call->replies, rep);
-       } else {
-               return STATUS_BUFFER_OVERFLOW;
        }
 
        if (call->replies == NULL) {
@@ -1151,31 +1144,7 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
                talloc_free(call);
        }
 
-       return NT_STATUS_OK;
-}
-
-
-/*
-  write_fn() for dcesrv_output_blob()
-*/
-static ssize_t dcesrv_output_blob_write_fn(void *private, DATA_BLOB *out)
-{
-       DATA_BLOB *blob = private;
-       if (out->length < blob->length) {
-               blob->length = out->length;
-       }
-       memcpy(blob->data, out->data, blob->length);
-       return blob->length;
-}
-
-/*
-  a simple wrapper for dcesrv_output() for when we want to output
-  into a data blob
-*/
-NTSTATUS dcesrv_output_blob(struct dcesrv_connection *dce_conn, 
-                           DATA_BLOB *blob)
-{
-       return dcesrv_output(dce_conn, blob, dcesrv_output_blob_write_fn);
+       return status;
 }
 
 static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_servers, uint32_t state_flags, struct dcesrv_context **_dce_ctx)
index 317655cfcfa18090e7e0d088b6d85611a73adef2..5bba948c088039eeb5b8bc1c9d046b3d5aa62bc0 100644 (file)
@@ -38,18 +38,17 @@ struct dcesrv_socket_context {
 /*
   write_fn callback for dcesrv_output()
 */
-static ssize_t dcerpc_write_fn(void *private, DATA_BLOB *out)
+static NTSTATUS dcerpc_write_fn(void *private_data, DATA_BLOB *out, size_t *nwritten)
 {
        NTSTATUS status;
-       struct socket_context *sock = private;
+       struct socket_context *sock = talloc_get_type(private_data, struct socket_context);
        size_t sendlen;
 
        status = socket_send(sock, out, &sendlen, 0);
-       if (NT_STATUS_IS_ERR(status)) {
-               return -1;
-       }
+       NT_STATUS_IS_ERR_RETURN(status);
 
-       return sendlen;
+       *nwritten = sendlen;
+       return status;
 }
 
 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)