summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/smb2_flush.c122
1 files changed, 97 insertions, 25 deletions
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
index 5164d1b4a4..37a8309b33 100644
--- a/source3/smbd/smb2_flush.c
+++ b/source3/smbd/smb2_flush.c
@@ -22,20 +22,23 @@
#include "smbd/globals.h"
#include "../source4/libcli/smb2/smb2_constants.h"
-static NTSTATUS smbd_smb2_flush(struct smbd_smb2_request *req,
- uint64_t in_file_id_volatile);
+static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbd_smb2_request *smb2req,
+ uint64_t in_file_id_volatile);
+static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req);
+static void smbd_smb2_request_flush_done(struct tevent_req *subreq);
NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
{
const uint8_t *inhdr;
const uint8_t *inbody;
int i = req->current_idx;
- DATA_BLOB outbody;
size_t expected_body_size = 0x18;
size_t body_size;
uint64_t in_file_id_persistent;
uint64_t in_file_id_volatile;
- NTSTATUS status;
+ struct tevent_req *subreq;
inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
@@ -56,65 +59,134 @@ NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
}
- status = smbd_smb2_flush(req,
- in_file_id_volatile);
+ subreq = smbd_smb2_flush_send(req,
+ req->conn->smb2.event_ctx,
+ req,
+ in_file_id_volatile);
+ if (subreq == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+ tevent_req_set_callback(subreq, smbd_smb2_request_flush_done, req);
+ return NT_STATUS_OK;
+}
+
+static void smbd_smb2_request_flush_done(struct tevent_req *subreq)
+{
+ struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+ struct smbd_smb2_request);
+ DATA_BLOB outbody;
+ NTSTATUS status;
+ NTSTATUS error; /* transport error */
+
+ status = smbd_smb2_flush_recv(subreq);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
+ error = smbd_smb2_request_error(req, status);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(req->conn,
+ nt_errstr(error));
+ return;
+ }
+ return;
}
outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(req->conn,
+ nt_errstr(error));
+ return;
+ }
+ return;
}
SSVAL(outbody.data, 0x00, 0x04); /* struct size */
SSVAL(outbody.data, 0x02, 0); /* reserved */
- return smbd_smb2_request_done(req, outbody, NULL);
+ error = smbd_smb2_request_done(req, outbody, NULL);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(req->conn,
+ nt_errstr(error));
+ return;
+ }
}
-static NTSTATUS smbd_smb2_flush(struct smbd_smb2_request *req,
- uint64_t in_file_id_volatile)
+struct smbd_smb2_flush_state {
+ struct smbd_smb2_request *smb2req;
+};
+
+static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbd_smb2_request *smb2req,
+ uint64_t in_file_id_volatile)
{
+ struct tevent_req *req;
+ struct smbd_smb2_flush_state *state;
NTSTATUS status;
struct smb_request *smbreq;
- connection_struct *conn = req->tcon->compat_conn;
files_struct *fsp;
+ req = tevent_req_create(mem_ctx, &state,
+ struct smbd_smb2_flush_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->smb2req = smb2req;
+
DEBUG(10,("smbd_smb2_flush: file_id[0x%016llX]\n",
(unsigned long long)in_file_id_volatile));
- smbreq = smbd_smb2_fake_smb_request(req);
- if (smbreq == NULL) {
- return NT_STATUS_NO_MEMORY;
+ smbreq = smbd_smb2_fake_smb_request(smb2req);
+ if (tevent_req_nomem(smbreq, req)) {
+ return tevent_req_post(req, ev);
}
- /* If it's an IPC, pass off the pipe handler. */
- if (IS_IPC(conn)) {
- return NT_STATUS_NOT_IMPLEMENTED;
+ if (IS_IPC(smbreq->conn)) {
+ tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ return tevent_req_post(req, ev);
}
fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
if (fsp == NULL) {
- return NT_STATUS_FILE_CLOSED;
+ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
+ return tevent_req_post(req, ev);
}
- if (conn != fsp->conn) {
- return NT_STATUS_FILE_CLOSED;
+ if (smbreq->conn != fsp->conn) {
+ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
+ return tevent_req_post(req, ev);
}
- if (req->session->vuid != fsp->vuid) {
- return NT_STATUS_FILE_CLOSED;
+ if (smb2req->session->vuid != fsp->vuid) {
+ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
+ return tevent_req_post(req, ev);
}
if (!CHECK_WRITE(fsp)) {
- return NT_STATUS_ACCESS_DENIED;
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return tevent_req_post(req, ev);
}
- status = sync_file(conn, fsp, true);
+ status = sync_file(smbreq->conn, fsp, true);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("smbd_smb2_flush: sync_file for %s returned %s\n",
fsp->fsp_name, nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+}
+
+static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req)
+{
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
return status;
}
+ tevent_req_received(req);
return NT_STATUS_OK;
}