[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha6-298-gfa7ddc7

Volker Lendecke vlendec at samba.org
Sat Jan 31 16:51:20 GMT 2009


The branch, master has been updated
       via  fa7ddc78b8da8265096b1cc45471e1c7c96ac994 (commit)
       via  72729bfaee6057c383e1b2b261893d2bd8ae9714 (commit)
       via  8b480b52cef385f555ca90c804132472e2173129 (commit)
       via  2d5ec28b3b065940cefdd491ad7c8fd1a58c3a5c (commit)
       via  8ef92f7e32af73d0cd215e8f259ba5fcd3d9812e (commit)
       via  e8b2b46caeff185faef5491cbbeaf799bcd1b1ec (commit)
       via  c2fe28ba598e7db2915b3bb5e7b8d281361a4c95 (commit)
       via  b797c056a60b519da6595ce728846dace5d1dfbd (commit)
       via  e60d69d67d4064d4aa26644c6bca2dfc1b0f4983 (commit)
      from  582b27be242ad4453e42020cf5309293710768c4 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit fa7ddc78b8da8265096b1cc45471e1c7c96ac994
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 16:17:25 2009 +0100

    Remove unused np_read sync wrapper

commit 72729bfaee6057c383e1b2b261893d2bd8ae9714
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 14:57:52 2009 +0100

    Make reply_pipe_read_andx async

commit 8b480b52cef385f555ca90c804132472e2173129
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 14:44:04 2009 +0100

    Remove unused np_write sync wrapper

commit 2d5ec28b3b065940cefdd491ad7c8fd1a58c3a5c
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 14:43:06 2009 +0100

    Make reply_pipe_write async

commit 8ef92f7e32af73d0cd215e8f259ba5fcd3d9812e
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 14:31:31 2009 +0100

    Make reply_pipe_write_and_X async

commit e8b2b46caeff185faef5491cbbeaf799bcd1b1ec
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 14:33:38 2009 +0100

    Make-np_write-handle-0-byte-writes-as-NT_STATUS_OK

commit c2fe28ba598e7db2915b3bb5e7b8d281361a4c95
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 14 15:53:35 2008 +0200

    Convert api_rpc_trans_reply to async np_*

commit b797c056a60b519da6595ce728846dace5d1dfbd
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 13:36:09 2009 +0100

    Add an async np_read wrapper

commit e60d69d67d4064d4aa26644c6bca2dfc1b0f4983
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Jan 31 12:43:25 2009 +0100

    Add an async np_write wrapper

-----------------------------------------------------------------------

Summary of changes:
 source3/include/proto.h           |   13 ++-
 source3/include/smb.h             |   16 +++
 source3/rpc_server/srv_pipe_hnd.c |  187 ++++++++++++++++++++++------
 source3/smbd/ipc.c                |  148 ++++++++++++++++++-----
 source3/smbd/pipes.c              |  247 +++++++++++++++++++++++++-----------
 5 files changed, 465 insertions(+), 146 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 9199d6c..fd55669 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6314,10 +6314,15 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
 		 const char *client_address,
 		 struct auth_serversupplied_info *server_info,
 		 struct fake_file_handle **phandle);
-NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data,
-		  size_t len, ssize_t *nwritten);
-NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len,
-		 ssize_t *nread, bool *is_data_outstanding);
+struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+				struct fake_file_handle *handle,
+				const uint8_t *data, size_t len);
+NTSTATUS np_write_recv(struct async_req *req, ssize_t *nwritten);
+struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+			       struct fake_file_handle *handle,
+			       uint8_t *data, size_t len);
+NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread,
+		      bool *is_data_outstanding);
 
 /* The following definitions come from rpc_server/srv_samr_util.c  */
 
diff --git a/source3/include/smb.h b/source3/include/smb.h
index be6ccbf..491dd76 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -624,7 +624,18 @@ struct smb_request {
 	uint16_t buflen;
 	const uint8_t *buf;
 	const uint8 *inbuf;
+
+	/*
+	 * Async handling in the main smb processing loop is directed by
+	 * outbuf: reply_xxx routines indicate sync behaviour by putting their
+	 * reply into "outbuf". If they leave it as NULL, they take of it
+	 * themselves, possibly later.
+	 *
+	 * If async handling is wanted, the reply_xxx routine must make sure
+	 * that it talloc_move()s the smb_req somewhere else.
+	 */
 	uint8 *outbuf;
+
 	size_t unread_bytes;
 	bool encrypted;
 	connection_struct *conn;
@@ -638,6 +649,11 @@ struct smb_request {
 	 * Here we collect the outbufs from the chain handlers
 	 */
 	uint8_t *chain_outbuf;
+
+	/*
+	 * state information for async smb handling
+	 */
+	void *async_priv;
 };
 
 /* Defines for the sent_oplock_break field above. */
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 0753476..0a4d94f 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -1109,66 +1109,179 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
 	return NT_STATUS_OK;
 }
 
-NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data,
-		  size_t len, ssize_t *nwritten)
+struct np_write_state {
+	ssize_t nwritten;
+};
+
+static void np_write_done(struct async_req *subreq);
+
+struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+				struct fake_file_handle *handle,
+				const uint8_t *data, size_t len)
 {
-	DEBUG(6, ("np_write: len: %d\n", (int)len));
+	struct async_req *result, *subreq;
+	struct np_write_state *state;
+	NTSTATUS status;
+
+	DEBUG(6, ("np_write_send: len: %d\n", (int)len));
 	dump_data(50, data, len);
 
-	switch (handle->type) {
-	case FAKE_FILE_TYPE_NAMED_PIPE: {
+	if (!async_req_setup(mem_ctx, &result, &state,
+			     struct np_write_state)) {
+		return NULL;
+	}
+
+	if (len == 0) {
+		state->nwritten = 0;
+		status = NT_STATUS_OK;
+		goto post_status;
+	}
+
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
 		struct pipes_struct *p = talloc_get_type_abort(
 			handle->private_data, struct pipes_struct);
-		*nwritten = write_to_internal_pipe(p, (char *)data, len);
-		break;
+
+		state->nwritten = write_to_internal_pipe(p, (char *)data, len);
+
+		status = (state->nwritten >= 0)
+			? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+		goto post_status;
 	}
-	case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: {
+
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
 		struct np_proxy_state *p = talloc_get_type_abort(
 			handle->private_data, struct np_proxy_state);
-		*nwritten = write_data(p->fd, (char *)data, len);
-		break;
+
+		state->nwritten = len;
+
+		subreq = sendall_send(state, ev, p->fd, data, len, 0);
+		if (subreq == NULL) {
+			goto fail;
+		}
+		subreq->async.fn = np_write_done;
+		subreq->async.priv = result;
+		return result;
 	}
-	default:
-		return NT_STATUS_INVALID_HANDLE;
-		break;
+
+	status = NT_STATUS_INVALID_HANDLE;
+ post_status:
+	if (async_post_status(result, ev, status)) {
+		return result;
 	}
+ fail:
+	TALLOC_FREE(result);
+	return NULL;
+}
 
-	return ((*nwritten) >= 0)
-		? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+static void np_write_done(struct async_req *subreq)
+{
+	struct async_req *req = talloc_get_type_abort(
+		subreq->async.priv, struct async_req);
+	NTSTATUS status;
+
+	status = sendall_recv(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		async_req_error(req, status);
+		return;
+	}
+	return async_req_done(req);
 }
 
-NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len,
-		 ssize_t *nread, bool *is_data_outstanding)
+NTSTATUS np_write_recv(struct async_req *req, ssize_t *pnwritten)
 {
-	switch (handle->type) {
-	case FAKE_FILE_TYPE_NAMED_PIPE: {
+	struct np_write_state *state = talloc_get_type_abort(
+		req->private_data, struct np_write_state);
+	NTSTATUS status;
+
+	if (async_req_is_error(req, &status)) {
+		return status;
+	}
+	*pnwritten = state->nwritten;
+	return NT_STATUS_OK;
+}
+
+struct np_read_state {
+	ssize_t nread;
+	bool is_data_outstanding;
+};
+
+static void np_read_done(struct async_req *subreq);
+
+struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+			       struct fake_file_handle *handle,
+			       uint8_t *data, size_t len)
+{
+	struct async_req *result, *subreq;
+	struct np_read_state *state;
+	NTSTATUS status;
+
+	if (!async_req_setup(mem_ctx, &result, &state,
+			     struct np_read_state)) {
+		return NULL;
+	}
+
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
 		struct pipes_struct *p = talloc_get_type_abort(
 			handle->private_data, struct pipes_struct);
-		*nread = read_from_internal_pipe(p, (char *)data, len,
-						 is_data_outstanding);
-		break;
+
+		state->nread = read_from_internal_pipe(
+			p, (char *)data, len, &state->is_data_outstanding);
+
+		status = (state->nread >= 0)
+			? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+		goto post_status;
 	}
-	case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: {
+
+	if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
 		struct np_proxy_state *p = talloc_get_type_abort(
 			handle->private_data, struct np_proxy_state);
-		int available = 0;
 
-		*nread = sys_read(p->fd, (char *)data, len);
+		state->nread = len;
 
-		/*
-		 * We don't look at the ioctl result. We don't really care
-		 * if there is data available, because this is racy anyway.
-		 */
-		ioctl(p->fd, FIONREAD, &available);
-		*is_data_outstanding = (available > 0);
+		subreq = recvall_send(state, ev, p->fd, data, len, 0);
+		if (subreq == NULL) {
+			goto fail;
+		}
+		subreq->async.fn = np_read_done;
+		subreq->async.priv = result;
+		return result;
+	}
 
-		break;
+	status = NT_STATUS_INVALID_HANDLE;
+ post_status:
+	if (async_post_status(result, ev, status)) {
+		return result;
 	}
-	default:
-		return NT_STATUS_INVALID_HANDLE;
-		break;
+ fail:
+	TALLOC_FREE(result);
+	return NULL;
+}
+
+static void np_read_done(struct async_req *subreq)
+{
+	struct async_req *req = talloc_get_type_abort(
+		subreq->async.priv, struct async_req);
+	NTSTATUS status;
+
+	status = recvall_recv(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		async_req_error(req, status);
+		return;
 	}
+	async_req_done(req);
+}
+
+NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread,
+		      bool *is_data_outstanding)
+{
+	struct np_read_state *state = talloc_get_type_abort(
+		req->private_data, struct np_read_state);
+	NTSTATUS status;
 
-	return ((*nread) >= 0)
-		? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+	if (async_req_is_error(req, &status)) {
+		return status;
+	}
+	*nread = state->nread;
+	*is_data_outstanding = state->is_data_outstanding;
+	return NT_STATUS_OK;
 }
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 7c15056..9c7528d 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -204,40 +204,137 @@ void send_trans_reply(connection_struct *conn,
  Start the first part of an RPC reply which began with an SMBtrans request.
 ****************************************************************************/
 
-static void api_rpc_trans_reply(connection_struct *conn,
-				struct smb_request *req,
-				files_struct *fsp,
-				int max_trans_reply)
+struct dcerpc_cmd_state {
+	struct fake_file_handle *handle;
+	uint8_t *data;
+	size_t num_data;
+	size_t max_read;
+};
+
+static void api_dcerpc_cmd_write_done(struct async_req *subreq);
+static void api_dcerpc_cmd_read_done(struct async_req *subreq);
+
+static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req,
+			   files_struct *fsp, uint8_t *data, size_t length,
+			   size_t max_read)
 {
-	bool is_data_outstanding;
-	uint8_t *rdata = SMB_MALLOC_ARRAY(uint8_t, max_trans_reply);
-	ssize_t data_len;
-	NTSTATUS status;
+	struct async_req *subreq;
+	struct dcerpc_cmd_state *state;
+
+	if (!fsp_is_np(fsp)) {
+		api_no_reply(conn, req);
+		return;
+	}
 
-	if(rdata == NULL) {
-		DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
+	state = talloc(req, struct dcerpc_cmd_state);
+	if (state == NULL) {
 		reply_nterror(req, NT_STATUS_NO_MEMORY);
 		return;
 	}
+	req->async_priv = state;
 
-	if (!fsp_is_np(fsp)) {
-		SAFE_FREE(rdata);
-		api_no_reply(conn,req);
+	state->handle = fsp->fake_file_handle;
+
+	/*
+	 * This memdup severely sucks. But doing it properly essentially means
+	 * to rewrite lanman.c, something which I don't really want to do now.
+	 */
+	state->data = (uint8_t *)talloc_memdup(state, data, length);
+	if (state->data == NULL) {
+		reply_nterror(req, NT_STATUS_NO_MEMORY);
 		return;
 	}
+	state->num_data = length;
+	state->max_read = max_read;
+
+	subreq = np_write_send(state, smbd_event_context(), state->handle,
+			       state->data, length);
+	if (subreq == NULL) {
+		TALLOC_FREE(state);
+		reply_nterror(req, NT_STATUS_NO_MEMORY);
+		return;
+	}
+	subreq->async.fn = api_dcerpc_cmd_write_done;
+	subreq->async.priv = talloc_move(conn, &req);
+}
+
+static void api_dcerpc_cmd_write_done(struct async_req *subreq)
+{
+	struct smb_request *req = talloc_get_type_abort(
+		subreq->async.priv, struct smb_request);
+	struct dcerpc_cmd_state *state = talloc_get_type_abort(
+		req->async_priv, struct dcerpc_cmd_state);
+	NTSTATUS status;
+	ssize_t nwritten = -1;
+
+	status = np_write_recv(subreq, &nwritten);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status) || (nwritten != state->num_data)) {
+		DEBUG(10, ("Could not write to pipe: %s (%d/%d)\n",
+			   nt_errstr(status), (int)state->num_data,
+			   (int)nwritten));
+		reply_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE);
+		goto send;
+	}
+
+	state->data = TALLOC_REALLOC_ARRAY(state, state->data, uint8_t,
+					   state->max_read);
+	if (state->data == NULL) {
+		reply_nterror(req, NT_STATUS_NO_MEMORY);
+		goto send;
+	}
+
+	subreq = np_read_send(req->conn, smbd_event_context(),
+			      state->handle, state->data, state->max_read);
+	if (subreq == NULL) {
+		reply_nterror(req, NT_STATUS_NO_MEMORY);
+		goto send;
+	}
+
+	subreq->async.fn = api_dcerpc_cmd_read_done;
+	subreq->async.priv = req;
+	return;
+
+ send:
+	if (!srv_send_smb(
+		    smbd_server_fd(), (char *)req->outbuf,
+		    IS_CONN_ENCRYPTED(req->conn) || req->encrypted)) {
+		exit_server_cleanly("construct_reply: srv_send_smb failed.");
+	}
+	TALLOC_FREE(req);
+}
+
+static void api_dcerpc_cmd_read_done(struct async_req *subreq)
+{
+	struct smb_request *req = talloc_get_type_abort(
+		subreq->async.priv, struct smb_request);
+	struct dcerpc_cmd_state *state = talloc_get_type_abort(
+		req->async_priv, struct dcerpc_cmd_state);
+	NTSTATUS status;
+	ssize_t nread;
+	bool is_data_outstanding;
+
+	status = np_read_recv(subreq, &nread, &is_data_outstanding);
+	TALLOC_FREE(subreq);
 
-	status = np_read(fsp->fake_file_handle, rdata, max_trans_reply,
-			 &data_len, &is_data_outstanding);
 	if (!NT_STATUS_IS_OK(status)) {
-		SAFE_FREE(rdata);
-		api_no_reply(conn,req);
+		DEBUG(10, ("Could not read from to pipe: %s\n",
+			   nt_errstr(status)));
+		reply_nterror(req, status);
+
+		if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+				  IS_CONN_ENCRYPTED(req->conn)
+				  ||req->encrypted)) {
+			exit_server_cleanly("construct_reply: srv_send_smb "
+					    "failed.");
+		}
+		TALLOC_FREE(req);
 		return;
 	}
 
-	send_trans_reply(conn, req, NULL, 0, (char *)rdata, data_len,
+	send_trans_reply(req->conn, req, NULL, 0, (char *)state->data, nread,
 			 is_data_outstanding);
-	SAFE_FREE(rdata);
-	return;
+	TALLOC_FREE(req);
 }
 
 /****************************************************************************
@@ -310,7 +407,6 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
 	struct files_struct *fsp;
 	int pnum;
 	int subcommand;
-	NTSTATUS status;
 
 	DEBUG(5,("api_fd_reply\n"));
 
@@ -360,14 +456,8 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
 	switch (subcommand) {
 	case TRANSACT_DCERPCCMD: {
 		/* dce/rpc command */
-		ssize_t nwritten;
-		status = np_write(fsp->fake_file_handle, data, tdscnt,
-				  &nwritten);
-		if (!NT_STATUS_IS_OK(status)) {
-			api_no_reply(conn, req);
-			return;
-		}
-		api_rpc_trans_reply(conn, req, fsp, mdrcnt);
+		api_dcerpc_cmd(conn, req, fsp, (uint8_t *)data, tdscnt,
+			       mdrcnt);
 		break;
 	}
 	case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index b148cff..f287adc 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -144,12 +144,18 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
  Reply to a write on a pipe.
 ****************************************************************************/
 
+struct pipe_write_state {
+	size_t numtowrite;
+};
+
+static void pipe_write_done(struct async_req *subreq);
+
 void reply_pipe_write(struct smb_request *req)
 {
 	files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0));
-	size_t numtowrite = SVAL(req->vwv+1, 0);
-	ssize_t nwritten;
 	const uint8_t *data;
+	struct pipe_write_state *state;
+	struct async_req *subreq;
 
 	if (!fsp_is_np(fsp)) {
 		reply_doserror(req, ERRDOS, ERRbadfid);
@@ -161,39 +167,59 @@ void reply_pipe_write(struct smb_request *req)
 		return;
 	}
 
+	state = talloc(req, struct pipe_write_state);
+	if (state == NULL) {
+		reply_nterror(req, NT_STATUS_NO_MEMORY);
+		return;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list