[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