[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Sat Jul 9 05:56:01 MDT 2011
The branch, master has been updated
via 244c856 s3:smb2cli_base: ask for the next response if there're still pending requests
via 8b4a368 s3:smb2cli_base: make use of tevent_req_defer_callback()
via facc110 s3:smb2cli_base: fix memory hierachy in smb2cli_req_recv()
via 504d092 s3:smb2cli_base: call smb2cli_req_unset_pending() before tevent_req_done()
via 242ca5d s3:smb2cli_base: unset the destructor in smb2cli_req_unset_pending()
via c55bfc0 s3:smb2cli_base: keep the order of pending requests
via a9f03f1 s3:smb2cli_base: rename 'result' => 'req' in smb2cli_req_create()
from 4768fc6 tevent: change version to 0.9.13 after adding tevent_req_defer_callback()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 244c856cbfee2d08c0d47241daa7adb6a32f5f24
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Jul 9 10:13:15 2011 +0200
s3:smb2cli_base: ask for the next response if there're still pending requests
metze
Autobuild-User: Stefan Metzmacher <metze at samba.org>
Autobuild-Date: Sat Jul 9 13:55:04 CEST 2011 on sn-devel-104
commit 8b4a3681e511adafe0efea3d64bad5135867477c
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Jul 9 10:12:11 2011 +0200
s3:smb2cli_base: make use of tevent_req_defer_callback()
In order to notify requests of transport layer errors,
we need to defer the triggering of the callbacks,
otherwise we may crash, if one of the callbacks
destroys the cli_state.
metze
commit facc110c79b9ec4e3b0509ad6b00e1fd464d3a33
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Jul 8 17:57:56 2011 +0200
s3:smb2cli_base: fix memory hierachy in smb2cli_req_recv()
We need to use talloc_reference() if there're more than one
response, but we use it in a way that the caller can't
call talloc_free() or talloc_unlink() on it.
metze
commit 504d092aa7d83304373b001cbe68c65a62a824bb
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Jul 9 10:42:21 2011 +0200
s3:smb2cli_base: call smb2cli_req_unset_pending() before tevent_req_done()
metze
commit 242ca5dba35ba282ddfe96751120810eadb4de8e
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Jul 9 10:40:30 2011 +0200
s3:smb2cli_base: unset the destructor in smb2cli_req_unset_pending()
metze
commit c55bfc0733dd4be99c17ff8ee60c8e669c12bc3f
Author: Stefan Metzmacher <metze at samba.org>
Date: Sat Jul 9 09:51:33 2011 +0200
s3:smb2cli_base: keep the order of pending requests
metze
commit a9f03f198292f9e88647c3e2c3491e68bab3e9cf
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Jul 8 17:59:51 2011 +0200
s3:smb2cli_base: rename 'result' => 'req' in smb2cli_req_create()
metze
-----------------------------------------------------------------------
Summary of changes:
source3/libsmb/smb2cli_base.c | 190 +++++++++++++++++++++---------
source3/libsmb/smb2cli_base.h | 1 -
source3/libsmb/smb2cli_query_directory.c | 9 +-
source3/libsmb/smb2cli_read.c | 9 +-
4 files changed, 142 insertions(+), 67 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/libsmb/smb2cli_base.c b/source3/libsmb/smb2cli_base.c
index 318f1a2..8760c30 100644
--- a/source3/libsmb/smb2cli_base.c
+++ b/source3/libsmb/smb2cli_base.c
@@ -37,7 +37,7 @@ struct smb2cli_req_state {
uint8_t hdr[64];
uint8_t pad[7]; /* padding space for compounding */
- uint8_t *inbuf;
+ /* always an array of 3 talloc elements */
struct iovec *recv_iov;
};
@@ -50,6 +50,8 @@ static void smb2cli_req_unset_pending(struct tevent_req *req)
int num_pending = talloc_array_length(cli->pending);
int i;
+ talloc_set_destructor(req, NULL);
+
if (num_pending == 1) {
/*
* The pending read_smb tevent_req is a child of
@@ -77,8 +79,8 @@ static void smb2cli_req_unset_pending(struct tevent_req *req)
/*
* Remove ourselves from the cli->pending array
*/
- if (num_pending > 1) {
- cli->pending[i] = cli->pending[num_pending-1];
+ for (; i < (num_pending - 1); i++) {
+ cli->pending[i] = cli->pending[i+1];
}
/*
@@ -137,27 +139,63 @@ static bool smb2cli_req_set_pending(struct tevent_req *req)
return true;
}
+static void smb2cli_notify_pending(struct cli_state *cli, NTSTATUS status)
+{
+ if (cli->fd != -1) {
+ close(cli->fd);
+ cli->fd = -1;
+ }
+
+ /*
+ * Cancel all pending requests. We don't do a for-loop walking
+ * cli->pending because that array changes in
+ * cli_smb_req_destructor().
+ */
+ while (talloc_array_length(cli->pending) > 0) {
+ struct tevent_req *req;
+ struct smb2cli_req_state *state;
+
+ req = cli->pending[0];
+ state = tevent_req_data(req, struct smb2cli_req_state);
+
+ smb2cli_req_unset_pending(req);
+
+ /*
+ * we need to defer the callback, because we may notify more
+ * then one caller.
+ */
+ tevent_req_defer_callback(req, state->ev);
+ tevent_req_nterror(req, status);
+ }
+}
+
struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct cli_state *cli,
- uint16_t cmd,
- uint32_t flags,
- const uint8_t *fixed,
- uint16_t fixed_len,
- const uint8_t *dyn,
- uint16_t dyn_len)
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ uint16_t cmd,
+ uint32_t flags,
+ const uint8_t *fixed,
+ uint16_t fixed_len,
+ const uint8_t *dyn,
+ uint16_t dyn_len)
{
- struct tevent_req *result;
+ struct tevent_req *req;
struct smb2cli_req_state *state;
- result = tevent_req_create(mem_ctx, &state,
- struct smb2cli_req_state);
- if (result == NULL) {
+ req = tevent_req_create(mem_ctx, &state,
+ struct smb2cli_req_state);
+ if (req == NULL) {
return NULL;
}
state->ev = ev;
state->cli = cli;
+ state->recv_iov = talloc_zero_array(state, struct iovec, 3);
+ if (state->recv_iov == NULL) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+
state->fixed = fixed;
state->fixed_len = fixed_len;
state->dyn = dyn;
@@ -174,7 +212,7 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
SIVAL(state->hdr, SMB2_HDR_TID, cli->smb2.tid);
SBVAL(state->hdr, SMB2_HDR_SESSION_ID, cli->smb2.uid);
- return result;
+ return req;
}
static void smb2cli_writev_done(struct tevent_req *subreq);
@@ -304,11 +342,8 @@ static void smb2cli_writev_done(struct tevent_req *subreq)
nwritten = writev_recv(subreq, &err);
TALLOC_FREE(subreq);
if (nwritten == -1) {
- if (state->cli->fd != -1) {
- close(state->cli->fd);
- state->cli->fd = -1;
- }
- tevent_req_nterror(req, map_nt_error_from_unix(err));
+ /* here, we need to notify all pending requests */
+ smb2cli_notify_pending(state->cli, map_nt_error_from_unix(err));
return;
}
}
@@ -437,65 +472,110 @@ static void smb2cli_inbuf_received(struct tevent_req *subreq)
struct cli_state *cli =
tevent_req_callback_data(subreq,
struct cli_state);
+ TALLOC_CTX *frame = talloc_stackframe();
struct tevent_req *req;
+ struct smb2cli_req_state *state;
struct iovec *iov;
int i, num_iov;
NTSTATUS status;
uint8_t *inbuf;
ssize_t received;
int err;
+ size_t num_pending;
- received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err);
+ received = read_smb_recv(subreq, frame, &inbuf, &err);
TALLOC_FREE(subreq);
if (received == -1) {
- if (cli->fd != -1) {
- close(cli->fd);
- cli->fd = -1;
- }
- status = map_nt_error_from_unix(err);
- goto fail;
+ /*
+ * We need to close the connection and notify
+ * all pending requests.
+ */
+ smb2cli_notify_pending(cli, map_nt_error_from_unix(err));
+ TALLOC_FREE(frame);
+ return;
}
- status = smb2cli_inbuf_parse_compound(inbuf, talloc_tos(),
+ status = smb2cli_inbuf_parse_compound(inbuf, frame,
&iov, &num_iov);
if (!NT_STATUS_IS_OK(status)) {
- goto fail;
+ /*
+ * if we cannot parse the incoming pdu,
+ * the connection becomes unusable.
+ *
+ * We need to close the connection and notify
+ * all pending requests.
+ */
+ smb2cli_notify_pending(cli, status);
+ TALLOC_FREE(frame);
+ return;
}
for (i=1; i<num_iov; i+=3) {
+ uint8_t *inbuf_ref = NULL;
struct iovec *cur = &iov[i];
uint8_t *inhdr = (uint8_t *)cur[0].iov_base;
- struct smb2cli_req_state *state;
req = cli_smb2_find_pending(
cli, BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
if (req == NULL) {
/*
- * oplock breaks ??
+ * TODO: handle oplock breaks and async responses
+ */
+
+ /*
+ * We need to close the connection and notify
+ * all pending requests.
*/
- goto fail;
+ smb2cli_notify_pending(cli, status);
+ TALLOC_FREE(frame);
+ return;
}
+ smb2cli_req_unset_pending(req);
state = tevent_req_data(req, struct smb2cli_req_state);
- if (i+3 >= num_iov) {
- /* last in chain */
- state->inbuf = inbuf;
+
+ /*
+ * There might be more than one response
+ * we need to defer the notifications
+ */
+ tevent_req_defer_callback(req, state->ev);
+
+ /*
+ * Note: here we use talloc_reference() in a way
+ * that does not expose it to the caller.
+ */
+ inbuf_ref = talloc_reference(state->recv_iov, inbuf);
+ if (tevent_req_nomem(inbuf_ref, req)) {
+ continue;
}
- state->recv_iov = cur;
+
+ /* copy the related buffers */
+ state->recv_iov[0] = cur[0];
+ state->recv_iov[1] = cur[1];
+ state->recv_iov[2] = cur[2];
+
tevent_req_done(req);
}
- return;
- fail:
+
+ TALLOC_FREE(frame);
+
+ num_pending = talloc_array_length(cli->pending);
+ if (num_pending == 0) {
+ /* no more pending requests, so we are done for now */
+ return;
+ }
+ req = cli->pending[0];
+ state = tevent_req_data(req, struct smb2cli_req_state);
+
/*
- * Cancel all pending requests. We don't do a for-loop walking
- * cli->pending because that array changes in
- * cli_smb_req_destructor().
+ * add the read_smb request that waits for the
+ * next answer from the server
*/
- while (talloc_array_length(cli->pending) > 0) {
- req = cli->pending[0];
- talloc_set_destructor(req, NULL);
- smb2cli_req_destructor(req);
- tevent_req_nterror(req, status);
+ subreq = read_smb_send(cli->pending, state->ev, cli->fd);
+ if (subreq == NULL) {
+ smb2cli_notify_pending(cli, NT_STATUS_NO_MEMORY);
+ return;
}
+ tevent_req_set_callback(subreq, smb2cli_inbuf_received, cli);
}
NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
@@ -509,23 +589,17 @@ NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
if (tevent_req_is_nterror(req, &status)) {
return status;
}
+
+ status = NT_STATUS(IVAL(state->recv_iov[0].iov_base, SMB2_HDR_STATUS));
+
if (body_size != 0) {
if (body_size != SVAL(state->recv_iov[1].iov_base, 0)) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
}
- talloc_steal(req, state->inbuf);
if (piov != NULL) {
- *piov = state->recv_iov;
+ *piov = talloc_move(mem_ctx, &state->recv_iov);
}
- return NT_STATUS(IVAL(state->recv_iov[0].iov_base, SMB2_HDR_STATUS));
-}
-
-uint8_t *smb2cli_req_inbuf(struct tevent_req *req)
-{
- struct smb2cli_req_state *state = tevent_req_data(
- req, struct smb2cli_req_state);
-
- return state->inbuf;
+ return status;
}
diff --git a/source3/libsmb/smb2cli_base.h b/source3/libsmb/smb2cli_base.h
index 09a6b7f..9c49a8c 100644
--- a/source3/libsmb/smb2cli_base.h
+++ b/source3/libsmb/smb2cli_base.h
@@ -42,6 +42,5 @@ struct tevent_req *smb2cli_req_send(TALLOC_CTX *mem_ctx,
uint16_t dyn_len);
NTSTATUS smb2cli_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct iovec **piov, int body_size);
-uint8_t *smb2cli_req_inbuf(struct tevent_req *req);
#endif
diff --git a/source3/libsmb/smb2cli_query_directory.c b/source3/libsmb/smb2cli_query_directory.c
index fc6c0b7..554b267 100644
--- a/source3/libsmb/smb2cli_query_directory.c
+++ b/source3/libsmb/smb2cli_query_directory.c
@@ -27,7 +27,7 @@
struct smb2cli_query_directory_state {
uint8_t fixed[32];
- uint8_t *inbuf;
+ struct iovec *recv_iov;
uint8_t *data;
uint32_t data_length;
};
@@ -97,7 +97,7 @@ static void smb2cli_query_directory_done(struct tevent_req *subreq)
struct iovec *iov;
uint16_t data_offset;
- status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 9);
+ status = smb2cli_req_recv(subreq, state, &iov, 9);
if (tevent_req_nterror(req, status)) {
return;
}
@@ -110,7 +110,8 @@ static void smb2cli_query_directory_done(struct tevent_req *subreq)
tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
return;
}
- state->inbuf = smb2cli_req_inbuf(subreq);
+
+ state->recv_iov = iov;
state->data = (uint8_t *)iov[2].iov_base;
tevent_req_done(req);
}
@@ -128,7 +129,7 @@ NTSTATUS smb2cli_query_directory_recv(struct tevent_req *req,
if (tevent_req_is_nterror(req, &status)) {
return status;
}
- talloc_steal(mem_ctx, state->inbuf);
+ talloc_steal(mem_ctx, state->recv_iov);
*data_length = state->data_length;
*data = state->data;
return NT_STATUS_OK;
diff --git a/source3/libsmb/smb2cli_read.c b/source3/libsmb/smb2cli_read.c
index 79224e5..c348c99 100644
--- a/source3/libsmb/smb2cli_read.c
+++ b/source3/libsmb/smb2cli_read.c
@@ -27,7 +27,7 @@
struct smb2cli_read_state {
uint8_t fixed[48];
- uint8_t *inbuf;
+ struct iovec *recv_iov;
uint8_t *data;
uint32_t data_length;
};
@@ -85,7 +85,7 @@ static void smb2cli_read_done(struct tevent_req *subreq)
struct iovec *iov;
uint8_t data_offset;
- status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 17);
+ status = smb2cli_req_recv(subreq, state, &iov, 17);
if (tevent_req_nterror(req, status)) {
return;
}
@@ -98,7 +98,8 @@ static void smb2cli_read_done(struct tevent_req *subreq)
tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
return;
}
- state->inbuf = smb2cli_req_inbuf(subreq);
+
+ state->recv_iov = iov;
state->data = (uint8_t *)iov[2].iov_base;
tevent_req_done(req);
}
@@ -114,7 +115,7 @@ NTSTATUS smb2cli_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
if (tevent_req_is_nterror(req, &status)) {
return status;
}
- talloc_steal(mem_ctx, state->inbuf);
+ talloc_steal(mem_ctx, state->recv_iov);
*data_length = state->data_length;
*data = state->data;
return NT_STATUS_OK;
--
Samba Shared Repository
More information about the samba-cvs
mailing list