*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "smbd/globals.h"
-#include "../source4/libcli/smb2/smb2_constants.h"
+#include "../libcli/smb/smb_common.h"
+#include "../lib/util/tevent_ntstatus.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,
+ struct files_struct *fsp);
+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;
+ NTSTATUS status;
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;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
+ struct files_struct *in_fsp;
+ struct tevent_req *subreq;
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ status = smbd_smb2_request_verify_sizes(req, 0x18);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
}
+ inbody = SMBD_SMB2_IN_BODY_PTR(req);
in_file_id_persistent = BVAL(inbody, 0x08);
in_file_id_volatile = BVAL(inbody, 0x10);
- if (in_file_id_persistent != 0) {
+ in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
+ if (in_fsp == NULL) {
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->sconn->ev_ctx,
+ req, in_fsp);
+ 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 smbd_smb2_request_pending_queue(req, subreq, 500);
+}
+
+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->sconn,
+ nt_errstr(error));
+ return;
+ }
+ return;
}
- outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
+ outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
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->sconn,
+ 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->sconn,
+ 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,
+ struct files_struct *fsp)
{
+ 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;
-
- 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;
+ req = tevent_req_create(mem_ctx, &state,
+ struct smbd_smb2_flush_state);
+ if (req == NULL) {
+ return NULL;
}
+ state->smb2req = smb2req;
- /* If it's an IPC, pass off the pipe handler. */
- if (IS_IPC(conn)) {
- return NT_STATUS_NOT_IMPLEMENTED;
- }
+ DEBUG(10,("smbd_smb2_flush: %s - %s\n",
+ fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- return NT_STATUS_FILE_CLOSED;
- }
- if (conn != fsp->conn) {
- return NT_STATUS_FILE_CLOSED;
+ smbreq = smbd_smb2_fake_smb_request(smb2req);
+ if (tevent_req_nomem(smbreq, req)) {
+ return tevent_req_post(req, ev);
}
- if (req->session->vuid != fsp->vuid) {
- return NT_STATUS_FILE_CLOSED;
+
+ if (IS_IPC(smbreq->conn)) {
+ tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ 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)));
+ fsp_str_dbg(fsp), 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;
}