struct tevent_req *smb2_ioctl_named_pipe(uint32_t ctl_code, struct tevent_context *ev, struct tevent_req *req, struct smbd_smb2_ioctl_state *state) { NTSTATUS status; uint8_t *out_data = NULL; uint32_t out_data_len = 0; if (ctl_code == FSCTL_PIPE_TRANSCEIVE) { struct tevent_req *subreq; if (!IS_IPC(state->smbreq->conn)) { tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); return tevent_req_post(req, ev); } if (state->fsp == NULL) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } if (!fsp_is_np(state->fsp)) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } DEBUG(10,("smbd_smb2_ioctl_send: np_write_send of size %u\n", (unsigned int)state->in_input.length )); subreq = np_write_send(state, ev, state->fsp->fake_file_handle, state->in_input.data, state->in_input.length); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, smbd_smb2_ioctl_pipe_write_done, req); return req; } if (state->fsp == NULL) { status = NT_STATUS_NOT_SUPPORTED; } else { status = SMB_VFS_FSCTL(state->fsp, state, ctl_code, state->smbreq->flags2, state->in_input.data, state->in_input.length, &out_data, state->in_max_output, &out_data_len); state->out_output = data_blob_const(out_data, out_data_len); if (NT_STATUS_IS_OK(status)) { tevent_req_done(req); return tevent_req_post(req, ev); } } if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { if (IS_IPC(state->smbreq->conn)) { status = NT_STATUS_FS_DRIVER_REQUIRED; } else { status = NT_STATUS_INVALID_DEVICE_REQUEST; } } tevent_req_nterror(req, status); return tevent_req_post(req, ev); }
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, uint32_t in_smbpid, uint64_t in_file_id_volatile, uint32_t in_length, uint64_t in_offset, uint32_t in_minimum, uint32_t in_remaining) { NTSTATUS status; struct tevent_req *req = NULL; struct smbd_smb2_read_state *state = NULL; struct smb_request *smbreq = NULL; connection_struct *conn = smb2req->tcon->compat_conn; files_struct *fsp = NULL; ssize_t nread = -1; struct lock_struct lock; int saved_errno; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_read_state); if (req == NULL) { return NULL; } state->smb2req = smb2req; state->in_length = in_length; state->in_offset = in_offset; state->in_minimum = in_minimum; state->out_data = data_blob_null; state->out_remaining = 0; DEBUG(10,("smbd_smb2_read: file_id[0x%016llX]\n", (unsigned long long)in_file_id_volatile)); smbreq = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smbreq, req)) { return tevent_req_post(req, ev); } fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile); if (fsp == NULL) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } if (conn != fsp->conn) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } if (smb2req->session->vuid != fsp->vuid) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } if (fsp->is_directory) { tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST); return tevent_req_post(req, ev); } state->fsp = fsp; state->in_file_id_volatile = in_file_id_volatile; if (IS_IPC(smbreq->conn)) { struct tevent_req *subreq = NULL; state->out_data = data_blob_talloc(state, NULL, in_length); if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) { return tevent_req_post(req, ev); } if (!fsp_is_np(fsp)) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } subreq = np_read_send(state, server_event_context(), fsp->fake_file_handle, state->out_data.data, state->out_data.length); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, smbd_smb2_read_pipe_done, req); return req; } if (!CHECK_READ(fsp, smbreq)) { tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return tevent_req_post(req, ev); } status = schedule_smb2_aio_read(fsp->conn, smbreq, fsp, state, &state->out_data, (SMB_OFF_T)in_offset, (size_t)in_length); if (NT_STATUS_IS_OK(status)) { /* * Doing an async read. Don't * send a "gone async" message * as we expect this to be less * than the client timeout period. * JRA. FIXME for offline files.. * FIXME. Add cancel code.. */ smb2req->async = true; return req; } if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { /* Real error in setting up aio. Fail. */ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } /* Fallback to synchronous. */ init_strict_lock_struct(fsp, in_file_id_volatile, in_offset, in_length, READ_LOCK, &lock); if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) { tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); return tevent_req_post(req, ev); } /* Try sendfile in preference. */ status = schedule_smb2_sendfile_read(smb2req, state); if (NT_STATUS_IS_OK(status)) { tevent_req_done(req); return tevent_req_post(req, ev); } else { if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } } /* Ok, read into memory. Allocate the out buffer. */ state->out_data = data_blob_talloc(state, NULL, in_length); if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) { SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); return tevent_req_post(req, ev); } nread = read_file(fsp, (char *)state->out_data.data, in_offset, in_length); saved_errno = errno; SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); DEBUG(10,("smbd_smb2_read: file %s handle [0x%016llX] offset=%llu " "len=%llu returned %lld\n", fsp_str_dbg(fsp), (unsigned long long)in_file_id_volatile, (unsigned long long)in_offset, (unsigned long long)in_length, (long long)nread)); status = smb2_read_complete(req, nread, saved_errno); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); } else { /* Success. */ tevent_req_done(req); } return tevent_req_post(req, ev); }
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, struct files_struct *fsp, uint32_t in_length, uint64_t in_offset, uint32_t in_minimum, uint32_t in_remaining) { NTSTATUS status; struct tevent_req *req = NULL; struct smbd_smb2_read_state *state = NULL; struct smb_request *smbreq = NULL; connection_struct *conn = smb2req->tcon->compat; ssize_t nread = -1; struct lock_struct lock; int saved_errno; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_read_state); if (req == NULL) { return NULL; } state->smb2req = smb2req; state->in_length = in_length; state->in_offset = in_offset; state->in_minimum = in_minimum; state->out_data = data_blob_null; state->out_remaining = 0; DEBUG(10,("smbd_smb2_read: %s - %s\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp))); smbreq = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smbreq, req)) { return tevent_req_post(req, ev); } state->smbreq = smbreq; if (fsp->is_directory) { tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST); return tevent_req_post(req, ev); } state->fsp = fsp; if (IS_IPC(smbreq->conn)) { struct tevent_req *subreq = NULL; state->out_data = data_blob_talloc(state, NULL, in_length); if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) { return tevent_req_post(req, ev); } if (!fsp_is_np(fsp)) { tevent_req_nterror(req, NT_STATUS_FILE_CLOSED); return tevent_req_post(req, ev); } subreq = np_read_send(state, ev, fsp->fake_file_handle, state->out_data.data, state->out_data.length); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, smbd_smb2_read_pipe_done, req); return req; } if (!CHECK_READ(fsp, smbreq)) { tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return tevent_req_post(req, ev); } status = schedule_smb2_aio_read(fsp->conn, smbreq, fsp, state, &state->out_data, (off_t)in_offset, (size_t)in_length); if (NT_STATUS_IS_OK(status)) { /* * Doing an async read, allow this * request to be canceled */ tevent_req_set_cancel_fn(req, smbd_smb2_read_cancel); return req; } if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { /* Real error in setting up aio. Fail. */ tevent_req_nterror(req, status); return tevent_req_post(req, ev); } /* Fallback to synchronous. */ init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id, in_offset, in_length, READ_LOCK, &lock); if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) { tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); return tevent_req_post(req, ev); } /* Try sendfile in preference. */ status = schedule_smb2_sendfile_read(smb2req, state); if (NT_STATUS_IS_OK(status)) { tevent_req_done(req); return tevent_req_post(req, ev); } else { if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) { SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } } /* Ok, read into memory. Allocate the out buffer. */ state->out_data = data_blob_talloc(state, NULL, in_length); if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) { SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); return tevent_req_post(req, ev); } nread = read_file(fsp, (char *)state->out_data.data, in_offset, in_length); saved_errno = errno; SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); DEBUG(10,("smbd_smb2_read: file %s, %s, offset=%llu " "len=%llu returned %lld\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), (unsigned long long)in_offset, (unsigned long long)in_length, (long long)nread)); status = smb2_read_complete(req, nread, saved_errno); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); } else { /* Success. */ tevent_req_done(req); } return tevent_req_post(req, ev); }