mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r8021: we only need to return STATUS_BUFFER_OVERFLOW for the ipc_trans replies
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 commit is contained in:
parent
d04057b932
commit
fe483dcd87
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user