summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/rpc/dcerpc.c46
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c19
-rw-r--r--source4/librpc/rpc/dcerpc_sock.c6
3 files changed, 36 insertions, 35 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 352972b0b7..2c0dbcd5f3 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -756,6 +756,8 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p,
/*
process a fragment received from the transport layer during a
request
+
+ This function frees the data
*/
static void dcerpc_request_recv_data(struct dcerpc_connection *c,
DATA_BLOB *data,
@@ -766,6 +768,8 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
uint_t length;
if (!NT_STATUS_IS_OK(status)) {
+ data_blob_free(data);
+
/* all pending requests get the error */
while (c->pending) {
req = c->pending;
@@ -781,7 +785,7 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
pkt.call_id = 0;
- status = ncacn_pull_request_sign(c, data, (TALLOC_CTX *)data->data, &pkt);
+ status = ncacn_pull_request_sign(c, data, data->data, &pkt);
/* find the matching request. Notice we match before we check
the status. this is ok as a pending call_id can never be
@@ -792,29 +796,20 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
if (req == NULL) {
DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt.call_id));
+ data_blob_free(data);
return;
}
if (!NT_STATUS_IS_OK(status)) {
req->status = status;
- req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
- if (req->async.callback) {
- req->async.callback(req);
- }
- return;
+ goto req_done;
}
if (pkt.ptype == DCERPC_PKT_FAULT) {
DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt.u.fault.status)));
req->fault_code = pkt.u.fault.status;
req->status = NT_STATUS_NET_WRITE_FAULT;
- req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
- if (req->async.callback) {
- req->async.callback(req);
- }
- return;
+ goto req_done;
}
if (pkt.ptype != DCERPC_PKT_RESPONSE) {
@@ -822,12 +817,7 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
(int)pkt.ptype));
req->fault_code = DCERPC_FAULT_OTHER;
req->status = NT_STATUS_NET_WRITE_FAULT;
- req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
- if (req->async.callback) {
- req->async.callback(req);
- }
- return;
+ goto req_done;
}
length = pkt.u.response.stub_and_verifier.length;
@@ -839,12 +829,7 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
req->payload.length + length);
if (!req->payload.data) {
req->status = NT_STATUS_NO_MEMORY;
- req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
- if (req->async.callback) {
- req->async.callback(req);
- }
- return;
+ goto req_done;
}
memcpy(req->payload.data+req->payload.length,
pkt.u.response.stub_and_verifier.data, length);
@@ -853,19 +838,22 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
if (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
c->transport.send_read(c);
+ data_blob_free(data);
return;
}
- /* we've got the full payload */
- req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
-
if (!(pkt.drep[0] & DCERPC_DREP_LE)) {
req->flags |= DCERPC_PULL_BIGENDIAN;
} else {
req->flags &= ~DCERPC_PULL_BIGENDIAN;
}
+
+req_done:
+ /* we've got the full payload */
+ req->state = RPC_REQUEST_DONE;
+ DLIST_REMOVE(c->pending, req);
+ data_blob_free(data);
if (req->async.callback) {
req->async.callback(req);
}
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index b63a3080f5..bc48d674bf 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -89,9 +89,11 @@ static void smb_read_callback(struct smbcli_request *req)
frag_length = dcerpc_get_frag_length(&state->data);
if (frag_length <= state->received) {
- state->data.length = state->received;
- state->c->transport.recv_data(state->c, &state->data, NT_STATUS_OK);
+ DATA_BLOB data = state->data;
+ data.length = state->received;
+ talloc_steal(state->c, data.data);
talloc_free(state);
+ state->c->transport.recv_data(state->c, &data, NT_STATUS_OK);
return;
}
@@ -204,8 +206,10 @@ static void smb_trans_callback(struct smbcli_request *req)
}
if (!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
- c->transport.recv_data(c, &state->trans->out.data, NT_STATUS_OK);
+ DATA_BLOB data = state->trans->out.data;
+ talloc_steal(c, data.data);
talloc_free(state);
+ c->transport.recv_data(c, &data, NT_STATUS_OK);
return;
}
@@ -257,6 +261,8 @@ static NTSTATUS smb_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *b
state->req->async.fn = smb_trans_callback;
state->req->async.private = state;
+ talloc_steal(state, state->req);
+
return NT_STATUS_OK;
}
@@ -322,6 +328,7 @@ static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c)
{
struct smb_private *smb = c->transport.private;
union smb_close io;
+ struct smbcli_request *req;
/* maybe we're still starting up */
if (!smb) return NT_STATUS_OK;
@@ -329,7 +336,11 @@ static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c)
io.close.level = RAW_CLOSE_CLOSE;
io.close.in.fnum = smb->fnum;
io.close.in.write_time = 0;
- smb_raw_close(smb->tree, &io);
+ req = smb_raw_close_send(smb->tree, &io);
+ if (req != NULL) {
+ /* we don't care if this fails, so just free it if it succeeds */
+ req->async.fn = (void (*)(struct smbcli_request *))talloc_free;
+ }
talloc_free(smb);
diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c
index d7f87e9706..161c9a56dc 100644
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -120,6 +120,7 @@ static void sock_process_recv(struct dcerpc_connection *p)
struct sock_private *sock = p->transport.private;
NTSTATUS status;
size_t nread;
+ DATA_BLOB data;
if (sock->recv.data.data == NULL) {
sock->recv.data = data_blob_talloc(sock, NULL, MIN_HDR_SIZE);
@@ -176,14 +177,15 @@ static void sock_process_recv(struct dcerpc_connection *p)
}
/* we have a full packet */
- p->transport.recv_data(p, &sock->recv.data, NT_STATUS_OK);
- talloc_free(sock->recv.data.data);
+ data = sock->recv.data;
sock->recv.data = data_blob(NULL, 0);
sock->recv.received = 0;
sock->recv.pending_count--;
if (sock->recv.pending_count == 0) {
EVENT_FD_NOT_READABLE(sock->fde);
}
+
+ p->transport.recv_data(p, &data, NT_STATUS_OK);
}
/*