struct tevent_req *smb1cli_trans_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbXcli_conn *conn, uint8_t cmd, uint8_t additional_flags, uint8_t clear_flags, uint16_t additional_flags2, uint16_t clear_flags2, uint32_t timeout_msec, uint32_t pid, uint16_t tid, uint16_t uid, const char *pipe_name, uint16_t fid, uint16_t function, int flags, uint16_t *setup, uint8_t num_setup, uint8_t max_setup, uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data) { struct tevent_req *req, *subreq; struct smb1cli_trans_state *state; int iov_count; uint8_t wct; NTSTATUS status; charset_t charset; req = tevent_req_create(mem_ctx, &state, struct smb1cli_trans_state); if (req == NULL) { return NULL; } if ((cmd == SMBtrans) || (cmd == SMBtrans2)) { if ((num_param > 0xffff) || (max_param > 0xffff) || (num_data > 0xffff) || (max_data > 0xffff)) { DEBUG(3, ("Attempt to send invalid trans2 request " "(setup %u, params %u/%u, data %u/%u)\n", (unsigned)num_setup, (unsigned)num_param, (unsigned)max_param, (unsigned)num_data, (unsigned)max_data)); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); } } /* * The largest wct will be for nttrans (19+num_setup). Make sure we * don't overflow state->vwv in smb1cli_trans_format. */ if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); } state->conn = conn; state->ev = ev; state->cmd = cmd; state->additional_flags = additional_flags; state->clear_flags = clear_flags; state->additional_flags2 = additional_flags2; state->clear_flags2 = clear_flags2; state->timeout_msec = timeout_msec; state->flags = flags; state->num_rsetup = 0; state->rsetup = NULL; state->pid = pid; state->tid = tid; state->uid = uid; ZERO_STRUCT(state->rparam); ZERO_STRUCT(state->rdata); if (smbXcli_conn_use_unicode(conn)) { charset = CH_UTF16LE; } else { charset = CH_DOS; } if ((pipe_name != NULL) && (!convert_string_talloc(state, CH_UNIX, charset, pipe_name, strlen(pipe_name) + 1, &state->pipe_name_conv, &state->pipe_name_conv_len))) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return tevent_req_post(req, ev); } state->fid = fid; /* trans2 */ state->function = function; /* nttrans */ state->setup = setup; state->num_setup = num_setup; state->max_setup = max_setup; state->param = param; state->num_param = num_param; state->param_sent = 0; state->rparam.max = max_param; state->data = data; state->num_data = num_data; state->data_sent = 0; state->rdata.max = max_data; smb1cli_trans_format(state, &wct, &iov_count); subreq = smb1cli_req_create(state, ev, conn, cmd, state->additional_flags, state->clear_flags, state->additional_flags2, state->clear_flags2, state->timeout_msec, state->pid, state->tid, state->uid, wct, state->vwv, iov_count, state->iov); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } status = smb1cli_req_chain_submit(&subreq, 1); if (tevent_req_nterror(req, status)) { return tevent_req_post(req, state->ev); } tevent_req_set_callback(subreq, smb1cli_trans_done, req); /* * Now get the MID of the primary request * and mark it as persistent. This means * we will able to send and receive multiple * SMB pdus using this MID in both directions * (including correct SMB signing). */ state->mid = smb1cli_req_mid(subreq); smb1cli_req_set_mid(subreq, state->mid); state->primary_subreq = subreq; talloc_set_destructor(state, smb1cli_trans_state_destructor); tevent_req_set_cancel_fn(req, smb1cli_trans_cancel); return req; }
static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, struct files_struct *fsp, uint16_t in_flags, uint32_t in_output_buffer_length, uint64_t in_completion_filter) { struct tevent_req *req; struct smbd_smb2_notify_state *state; struct smb_request *smbreq; connection_struct *conn = smb2req->tcon->compat; bool recursive = (in_flags & SMB2_WATCH_TREE) ? true : false; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_notify_state); if (req == NULL) { return NULL; } state->smb2req = smb2req; state->status = NT_STATUS_INTERNAL_ERROR; state->out_output_buffer = data_blob_null; talloc_set_destructor(state, smbd_smb2_notify_state_destructor); DEBUG(10,("smbd_smb2_notify_send: %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; smbreq->async_priv = (void *)req; if (DEBUGLEVEL >= 3) { char *filter_string; filter_string = notify_filter_string(NULL, in_completion_filter); if (tevent_req_nomem(filter_string, req)) { return tevent_req_post(req, ev); } DEBUG(3,("smbd_smb2_notify_send: notify change " "called on %s, filter = %s, recursive = %d\n", fsp_str_dbg(fsp), filter_string, recursive)); TALLOC_FREE(filter_string); } if ((!fsp->is_directory) || (conn != fsp->conn)) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } if (fsp->notify == NULL) { status = change_notify_create(fsp, in_completion_filter, recursive); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("change_notify_create returned %s\n", nt_errstr(status))); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } } if (change_notify_fsp_has_changes(fsp)) { /* * We've got changes pending, respond immediately */ /* * TODO: write a torture test to check the filtering behaviour * here. */ change_notify_reply(smbreq, NT_STATUS_OK, in_output_buffer_length, fsp->notify, smbd_smb2_notify_reply); /* * change_notify_reply() above has independently * called tevent_req_done(). */ return tevent_req_post(req, ev); } /* * No changes pending, queue the request */ status = change_notify_add_request(smbreq, in_output_buffer_length, in_completion_filter, recursive, fsp, smbd_smb2_notify_reply); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return tevent_req_post(req, ev); } /* * This is a HACK! * * change_notify_add_request() talloc_moves() * smbreq away from us, so we need a destructor * which moves it back at the end. */ state->has_request = true; talloc_set_destructor(smbreq, smbd_smb2_notify_smbreq_destructor); /* allow this request to be canceled */ tevent_req_set_cancel_fn(req, smbd_smb2_notify_cancel); SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(state->smb2req->profile); return req; }
static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, struct files_struct *fsp, uint16_t in_flags, uint32_t in_output_buffer_length, uint64_t in_completion_filter) { struct tevent_req *req; struct smbd_smb2_notify_state *state; struct smb_request *smbreq; connection_struct *conn = smb2req->tcon->compat_conn; bool recursive = (in_flags & 0x0001) ? true : false; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_notify_state); if (req == NULL) { return NULL; } state->smb2req = smb2req; state->status = NT_STATUS_INTERNAL_ERROR; state->out_output_buffer = data_blob_null; state->im = NULL; DEBUG(10,("smbd_smb2_notify_send: %s - fnum[%d]\n", fsp_str_dbg(fsp), fsp->fnum)); smbreq = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smbreq, req)) { return tevent_req_post(req, ev); } state->smbreq = smbreq; smbreq->async_priv = (void *)req; { char *filter_string; filter_string = notify_filter_string(NULL, in_completion_filter); if (tevent_req_nomem(filter_string, req)) { return tevent_req_post(req, ev); } DEBUG(3,("smbd_smb2_notify_send: notify change " "called on %s, filter = %s, recursive = %d\n", fsp_str_dbg(fsp), filter_string, recursive)); TALLOC_FREE(filter_string); } if ((!fsp->is_directory) || (conn != fsp->conn)) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } if (fsp->notify == NULL) { status = change_notify_create(fsp, in_completion_filter, recursive); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("change_notify_create returned %s\n", nt_errstr(status))); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } } if (fsp->notify->num_changes != 0) { /* * We've got changes pending, respond immediately */ /* * TODO: write a torture test to check the filtering behaviour * here. */ change_notify_reply(smbreq, NT_STATUS_OK, in_output_buffer_length, fsp->notify, smbd_smb2_notify_reply); /* * change_notify_reply() above has independently * called tevent_req_done(). */ return tevent_req_post(req, ev); } state->im = tevent_create_immediate(state); if (tevent_req_nomem(state->im, req)) { return tevent_req_post(req, ev); } /* * No changes pending, queue the request */ status = change_notify_add_request(smbreq, in_output_buffer_length, in_completion_filter, recursive, fsp, smbd_smb2_notify_reply); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return tevent_req_post(req, ev); } /* allow this request to be canceled */ tevent_req_set_cancel_fn(req, smbd_smb2_notify_cancel); return req; }
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); }