1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00

Convert api_rpc_trans_reply to async np_*

This commit is contained in:
Volker Lendecke 2008-10-14 15:53:35 +02:00
parent b797c056a6
commit c2fe28ba59
2 changed files with 137 additions and 31 deletions

View File

@ -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. */

View File

@ -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)
{
bool is_data_outstanding;
uint8_t *rdata = SMB_MALLOC_ARRAY(uint8_t, max_trans_reply);
ssize_t data_len;
NTSTATUS status;
struct dcerpc_cmd_state {
struct fake_file_handle *handle;
uint8_t *data;
size_t num_data;
size_t max_read;
};
if(rdata == NULL) {
DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
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)
{
struct async_req *subreq;
struct dcerpc_cmd_state *state;
if (!fsp_is_np(fsp)) {
api_no_reply(conn, req);
return;
}
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;
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);
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);
}
send_trans_reply(conn, req, NULL, 0, (char *)rdata, data_len,
is_data_outstanding);
SAFE_FREE(rdata);
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);
if (!NT_STATUS_IS_OK(status)) {
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(req->conn, req, NULL, 0, (char *)state->data, nread,
is_data_outstanding);
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: