static void open_socket_out_connected(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct open_socket_out_state *state = tevent_req_data(req, struct open_socket_out_state); int ret; int sys_errno; ret = async_connect_recv(subreq, &sys_errno); TALLOC_FREE(subreq); if (ret == 0) { tevent_req_done(req); return; } if ( #ifdef ETIMEDOUT (sys_errno == ETIMEDOUT) || #endif (sys_errno == EINPROGRESS) || (sys_errno == EALREADY) || (sys_errno == EAGAIN)) { /* * retry */ if (state->wait_usec < 250000) { state->wait_usec *= 1.5; } subreq = async_connect_send(state, state->ev, state->fd, (struct sockaddr *)&state->ss, state->salen); if (tevent_req_nomem(subreq, req)) { return; } if (!tevent_req_set_endtime( subreq, state->ev, timeval_current_ofs_usec(state->wait_usec))) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } tevent_req_set_callback(subreq, open_socket_out_connected, req); return; } #ifdef EISCONN if (sys_errno == EISCONN) { tevent_req_done(req); return; } #endif /* real error */ tevent_req_nterror(req, map_nt_error_from_unix(sys_errno)); }
struct tevent_req *smb2_ioctl_dfs(uint32_t ctl_code, struct tevent_context *ev, struct tevent_req *req, struct smbd_smb2_ioctl_state *state) { NTSTATUS status; switch (ctl_code) { case FSCTL_DFS_GET_REFERRALS: status = fsctl_dfs_get_refers(state, ev, state->smbreq->conn, &state->in_input, state->in_max_output, &state->out_output); if (!tevent_req_nterror(req, status)) { tevent_req_done(req); } return tevent_req_post(req, ev); break; default: { uint8_t *out_data = NULL; uint32_t out_data_len = 0; 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); break; } } tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return tevent_req_post(req, ev); }
void setent_notify(struct setent_req_list **list, errno_t err) { struct setent_req_list *reql; /* Notify the waiting clients */ while ((reql = *list) != NULL) { /* Each tevent_req_done() call will free * the request, removing it from the list. */ if (err == EOK) { tevent_req_done(reql->req); } else { tevent_req_error(reql->req, err); } if (reql == *list) { /* The consumer failed to free the * request. Log a bug and continue. */ DEBUG(SSSDBG_FATAL_FAILURE, ("BUG: a callback did not free its request. " "May leak memory\n")); /* Skip to the next since a memory leak is non-fatal */ *list = (*list)->next; } } }
static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_smart_refresh_state *state = NULL; char *highest_usn = NULL; int dp_error; int error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &dp_error, &error, &highest_usn, NULL); if (ret != EOK || dp_error != DP_ERR_OK || error != EOK) { goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n"); /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } done: if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct smbd_smb2_ioctl_state *state = tevent_req_data(req, struct smbd_smb2_ioctl_state); NTSTATUS status; ssize_t nread = -1; bool is_data_outstanding = false; status = np_read_recv(subreq, &nread, &is_data_outstanding); DEBUG(10,("smbd_smb2_ioctl_pipe_read_done: np_read_recv nread = %d " "is_data_outstanding = %d, status = %s\n", (int)nread, (int)is_data_outstanding, nt_errstr(status) )); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } state->out_output.length = nread; if (is_data_outstanding) { tevent_req_nterror(req, STATUS_BUFFER_OVERFLOW); return; } tevent_req_done(req); }
static void smbd_smb2_read_pipe_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct smbd_smb2_read_state *state = tevent_req_data(req, struct smbd_smb2_read_state); NTSTATUS status; ssize_t nread = -1; bool is_data_outstanding; status = np_read_recv(subreq, &nread, &is_data_outstanding); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } if (nread == 0 && state->out_data.length != 0) { tevent_req_nterror(req, NT_STATUS_END_OF_FILE); return; } state->out_data.length = nread; state->out_remaining = 0; /* * TODO: add STATUS_BUFFER_OVERFLOW handling, once we also * handle it in SMB1 pipe_read_andx_done(). */ tevent_req_done(req); }
static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_rules_refresh_state *state = NULL; char *highest_usn = NULL; size_t downloaded_rules_num; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error, &highest_usn, &downloaded_rules_num); talloc_zfree(subreq); if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) { goto done; } /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } if (downloaded_rules_num != state->num_rules) { state->error = ENOENT; } done: if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static void smb2_ipc_getinfo(struct tevent_req *req, struct smbd_smb2_getinfo_state *state, struct tevent_context *ev, uint8_t in_info_type, uint8_t in_file_info_class) { /* We want to reply to SMB2_GETINFO_FILE with a class of SMB2_FILE_STANDARD_INFO as otherwise a Win7 client issues this request twice (2xroundtrips) if we return NOT_SUPPORTED. NB. We do the same for SMB1 in call_trans2qpipeinfo() */ if (in_info_type == 0x01 && /* SMB2_GETINFO_FILE */ in_file_info_class == 0x05) { /* SMB2_FILE_STANDARD_INFO */ state->out_output_buffer = data_blob_talloc(state, NULL, 24); if (tevent_req_nomem(state->out_output_buffer.data, req)) { return; } memset(state->out_output_buffer.data,0,24); SOFF_T(state->out_output_buffer.data,0,4096LL); SIVAL(state->out_output_buffer.data,16,1); SIVAL(state->out_output_buffer.data,20,1); tevent_req_done(req); } else { tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); } }
static void sbus_request_notify_success(hash_table_t *table, const char *key, struct tevent_req *req, sbus_request_messages_fn messages_fn, DBusMessage *reply) { struct sbus_request_list *mainreq = NULL; struct sbus_request_list *list; struct sbus_request_list *item; errno_t ret; list = sbus_requests_lookup(table, key); if (list == NULL) { /* This was the only request with no key generator available. */ tevent_req_done(req); return; } /* First notify all chained D-Bus requests so we can steal the reply. */ DLIST_FOR_EACH(item, list) { /* Remember the main request. */ if (item->req == req) { mainreq = item; continue; } /* We don't want to notify current, invalid or non D-Bus request. */ if (!item->is_dbus || item->is_invalid) { continue; } ret = sbus_request_switch_reply(reply, item->req, messages_fn); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to switch reply for %p, " "terminating this request!\n", item->req); sbus_requests_finish(item, ret); continue; } sbus_requests_finish(item, EOK); } /* Now we finish the main request. */ sbus_requests_finish(mainreq, EOK); /* And as last, we notify all await requests. */ DLIST_FOR_EACH(item, list) { if (item->is_dbus) { continue; } sbus_requests_finish(item, EOK); } sbus_requests_delete(list); }
struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *uri, struct sockaddr_storage *addr, int addr_len, int timeout) { int ret = EOK; struct tevent_req *req; struct sss_ldap_init_state *state; req = tevent_req_create(mem_ctx, &state, struct sss_ldap_init_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n"); return NULL; } talloc_set_destructor((TALLOC_CTX *)state, sss_ldap_init_state_destructor); state->ldap = NULL; state->sd = -1; state->uri = uri; #ifdef HAVE_LDAP_INIT_FD struct tevent_req *subreq; subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout); if (subreq == NULL) { ret = ENOMEM; DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n"); goto fail; } tevent_req_set_callback(subreq, sss_ldap_init_sys_connect_done, req); return req; fail: tevent_req_error(req, ret); #else DEBUG(SSSDBG_MINOR_FAILURE, "ldap_init_fd not available, " "will use ldap_initialize with uri [%s].\n", uri); ret = ldap_initialize(&state->ldap, uri); if (ret == LDAP_SUCCESS) { tevent_req_done(req); } else { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_initialize failed [%s].\n", sss_ldap_err2string(ret)); if (ret == LDAP_SERVER_DOWN) { tevent_req_error(req, ETIMEDOUT); } else { tevent_req_error(req, EIO); } } #endif tevent_req_post(req, ev); return req; }
static bool smbd_smb2_notify_cancel(struct tevent_req *req) { struct smbd_smb2_notify_state *state = tevent_req_data(req, struct smbd_smb2_notify_state); smbd_notify_cancel_by_smbreq(state->smbreq); state->smb2req->cancelled = true; tevent_req_done(req); return true; }
int foo_done(TALLOC_CTX *mem_ctx, struct tevent_req **req) { // do some computation with data printf("prg> doing an event computation\n"); // set event as successful // This sets the request as TEVENT_REQ_DONE tevent_req_done(*req); // request can end up being unsuccessful // It sets TEVENT_REQ_USER_ERROR // tevent_req_error(*req, }
static void wb_next_pwent_fill_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); struct wb_next_pwent_state *state = tevent_req_data( req, struct wb_next_pwent_state); NTSTATUS status; status = wb_fill_pwent_recv(subreq); TALLOC_FREE(subreq); /* * When you try to enumerate users with 'getent passwd' and the user * doesn't have a uid set we should just move on. */ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { state->gstate->next_user += 1; if (state->gstate->next_user >= state->gstate->num_users) { TALLOC_FREE(state->gstate->users); state->gstate->domain = wb_next_find_domain(state->gstate->domain); if (state->gstate->domain == NULL) { tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES); return; } subreq = wb_query_user_list_send(state, state->ev, state->gstate->domain); if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, wb_next_pwent_fetch_done, req); return; } subreq = wb_fill_pwent_send(state, state->ev, &state->gstate->users[state->gstate->next_user], state->pw); if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, wb_next_pwent_fill_done, req); return; } else if (tevent_req_nterror(req, status)) { return; } state->gstate->next_user += 1; tevent_req_done(req); }
static void ctdb_conn_init_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); int ret, err; ret = async_connect_recv(subreq, &err); TALLOC_FREE(subreq); if (ret == -1) { tevent_req_error(req, err); return; } tevent_req_done(req); }
void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq, NTSTATUS subreq_status) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(subreq_status)) { tevent_req_nterror(req, subreq_status); return; } tevent_req_done(req); }
static void tsocket_writev_handler(struct tsocket_context *sock, void *private_data) { struct tevent_req *req = talloc_get_type(private_data, struct tevent_req); struct tsocket_writev_state *state = tevent_req_data(req, struct tsocket_writev_state); int ret; int err; bool retry; ret = tsocket_writev(state->caller.sock, state->iov, state->count); err = tsocket_error_from_errno(ret, errno, &retry); if (retry) { /* retry later */ return; } if (tevent_req_error(req, err)) { return; } state->total_written += ret; /* * we have not written everything yet, so we need to truncate * the already written bytes from our iov copy */ while (ret > 0) { if (ret < state->iov[0].iov_len) { uint8_t *base; base = (uint8_t *)state->iov[0].iov_base; base += ret; state->iov[0].iov_base = base; state->iov[0].iov_len -= ret; break; } ret -= state->iov[0].iov_len; state->iov += 1; state->count -= 1; } if (state->count > 0) { /* more to write */ return; } tevent_req_done(req); }
static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sss_ldap_init_state *state = tevent_req_data(req, struct sss_ldap_init_state); int ret; int lret; ret = sssd_async_socket_init_recv(subreq, &state->sd); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init request failed: [%d]: %s.\n", ret, sss_strerror(ret)); goto fail; } /* Initialize LDAP handler */ lret = ldap_init_fd(state->sd, LDAP_PROTO_TCP, state->uri, &state->ldap); if (lret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_init_fd failed: %s. [%d][%s]\n", sss_ldap_err2string(lret), state->sd, state->uri); ret = lret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO; goto fail; } if (ldap_is_ldaps_url(state->uri)) { lret = ldap_install_tls(state->ldap); if (lret != LDAP_SUCCESS) { if (lret == LDAP_LOCAL_ERROR) { DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n"); } else { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_install_tls failed: %s\n", sss_ldap_err2string(lret)); ret = EIO; goto fail; } } } tevent_req_done(req); return; fail: tevent_req_error(req, ret); }
static void smbd_smb2_notify_reply_trigger(struct tevent_context *ctx, struct tevent_immediate *im, void *private_data) { struct tevent_req *req = talloc_get_type_abort(private_data, struct tevent_req); struct smbd_smb2_notify_state *state = tevent_req_data(req, struct smbd_smb2_notify_state); if (!NT_STATUS_IS_OK(state->status)) { tevent_req_nterror(req, state->status); return; } tevent_req_done(req); }
static void sdap_sudo_full_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_full_refresh_state *state = NULL; char *highest_usn = NULL; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_full_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error, &highest_usn, NULL); talloc_zfree(subreq); if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) { goto done; } state->sudo_ctx->full_refresh_done = true; /* save the time in the sysdb */ ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL)); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of " "a successful full refresh\n"); /* this is only a minor error that does not affect the functionality, * therefore there is no need to report it with tevent_req_error() * which would cause problems in the consumers */ } DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n"); /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } done: state->sudo_ctx->full_refresh_in_progress = false; if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static struct tevent_req *aio_posix_pread_send( struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct files_struct *fsp, void *data, size_t n, off_t offset) { struct tevent_req *req; struct aio_posix_state *state; struct aiocb *a; int ret; req = tevent_req_create(mem_ctx, &state, struct aio_posix_state); if (req == NULL) { return NULL; } a = &state->acb; a->aio_fildes = fsp->fh->fd; a->aio_buf = data; a->aio_nbytes = n; a->aio_offset = offset; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_ptr = req; ret = aio_read(a); if (ret == 0) { talloc_set_destructor(state, aio_posix_state_destructor); return req; } if (errno == EAGAIN) { /* * aio overloaded, do the sync fallback */ state->ret = sys_pread(fsp->fh->fd, data, n, offset); if (state->ret == -1) { state->err = errno; } tevent_req_done(req); return tevent_req_post(req, ev); } tevent_req_error(req, errno); return tevent_req_post(req, ev); }
static void aio_posix_signal_handler(struct tevent_context *ev, struct tevent_signal *se, int signum, int count, void *_info, void *private_data) { siginfo_t *info; struct tevent_req *req; struct aio_posix_state *state; int err; info = (siginfo_t *)_info; req = talloc_get_type_abort(info->si_value.sival_ptr, struct tevent_req); state = tevent_req_data(req, struct aio_posix_state); err = aio_error(&state->acb); if (err == EINPROGRESS) { DEBUG(10, ("aio_posix_signal_handler: operation req %p " "still in progress\n", req)); return; } if (err == ECANCELED) { DEBUG(10, ("aio_posix_signal_handler: operation req %p " "canceled\n", req)); return; } /* * No need to suspend for this in the destructor anymore */ talloc_set_destructor(state, NULL); state->ret = aio_return(&state->acb); state->err = err; tevent_req_done(req); }
static void smbd_smb2_notify_reply(struct smb_request *smbreq, NTSTATUS error_code, uint8_t *buf, size_t len) { struct tevent_req *req = talloc_get_type_abort(smbreq->async_priv, struct tevent_req); struct smbd_smb2_notify_state *state = tevent_req_data(req, struct smbd_smb2_notify_state); if (state->skip_reply) { return; } SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(state->smb2req->profile); state->status = error_code; if (!NT_STATUS_IS_OK(error_code)) { /* nothing */ } else if (len == 0) { state->status = STATUS_NOTIFY_ENUM_DIR; } else { state->out_output_buffer = data_blob_talloc(state, buf, len); if (state->out_output_buffer.data == NULL) { state->status = NT_STATUS_NO_MEMORY; } } tevent_req_defer_callback(req, state->smb2req->sconn->ev_ctx); if (!NT_STATUS_IS_OK(state->status)) { tevent_req_nterror(req, state->status); return; } tevent_req_done(req); }
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); }
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); }
/* handle recv events on a cldap socket */ static bool cldap_socket_recv_dgram(struct cldap_socket *c, struct cldap_incoming *in) { DATA_BLOB blob; struct asn1_data *asn1; void *p; struct cldap_search_state *search; NTSTATUS status; if (in->recv_errno != 0) { goto error; } blob = data_blob_const(in->buf, in->len); asn1 = asn1_init(in); if (!asn1) { goto nomem; } if (!asn1_load(asn1, blob)) { goto nomem; } in->ldap_msg = talloc(in, struct ldap_message); if (in->ldap_msg == NULL) { goto nomem; } /* this initial decode is used to find the message id */ status = ldap_decode(asn1, NULL, in->ldap_msg); if (!NT_STATUS_IS_OK(status)) { goto nterror; } /* find the pending request */ p = idr_find(c->searches.idr, in->ldap_msg->messageid); if (p == NULL) { if (!c->incoming.handler) { TALLOC_FREE(in); return true; } /* this function should free or steal 'in' */ c->incoming.handler(c, c->incoming.private_data, in); return false; } search = talloc_get_type_abort(p, struct cldap_search_state); search->response.in = talloc_move(search, &in); search->response.asn1 = asn1; search->response.asn1->ofs = 0; DLIST_REMOVE(c->searches.list, search); if (cldap_recvfrom_setup(c)) { tevent_req_done(search->req); return true; } /* * This request was ok, just defer the notify of the caller * and then just fail the next request if needed */ tevent_req_defer_callback(search->req, search->caller.ev); tevent_req_done(search->req); status = NT_STATUS_NO_MEMORY; /* in is NULL it this point */ goto nterror; nomem: in->recv_errno = ENOMEM; error: status = map_nt_error_from_unix_common(in->recv_errno); nterror: TALLOC_FREE(in); /* in connected mode the first pending search gets the error */ if (!c->connected) { /* otherwise we just ignore the error */ return false; } if (!c->searches.list) { return false; } /* * We might called tevent_req_done() for a successful * search before, so we better deliver the failure * after the success, that is why we better also * use tevent_req_defer_callback() here. */ tevent_req_defer_callback(c->searches.list->req, c->searches.list->caller.ev); tevent_req_nterror(c->searches.list->req, status); return false; }
static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, struct files_struct *fsp, uint8_t in_info_type, uint8_t in_file_info_class, uint32_t in_output_buffer_length, DATA_BLOB in_input_buffer, uint32_t in_additional_information, uint32_t in_flags) { struct tevent_req *req; struct smbd_smb2_getinfo_state *state; struct smb_request *smbreq; connection_struct *conn = smb2req->tcon->compat; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_getinfo_state); if (req == NULL) { return NULL; } state->smb2req = smb2req; state->status = NT_STATUS_OK; state->out_output_buffer = data_blob_null; DEBUG(10,("smbd_smb2_getinfo_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); } if (IS_IPC(conn)) { smb2_ipc_getinfo(req, state, ev, in_info_type, in_file_info_class); return tevent_req_post(req, ev); } switch (in_info_type) { case SMB2_GETINFO_FILE: { uint16_t file_info_level; char *data = NULL; unsigned int data_size = 0; bool delete_pending = false; struct timespec write_time_ts; struct file_id fileid; struct ea_list *ea_list = NULL; int lock_data_count = 0; char *lock_data = NULL; size_t fixed_portion; ZERO_STRUCT(write_time_ts); switch (in_file_info_class) { case 0x0F:/* RAW_FILEINFO_SMB2_ALL_EAS */ file_info_level = 0xFF00 | in_file_info_class; break; case 0x12:/* RAW_FILEINFO_SMB2_ALL_INFORMATION */ file_info_level = 0xFF00 | in_file_info_class; break; default: /* the levels directly map to the passthru levels */ file_info_level = in_file_info_class + 1000; break; } if (fsp->fake_file_handle) { /* * This is actually for the QUOTA_FAKE_FILE --metze */ /* We know this name is ok, it's already passed the checks. */ } else if (fsp->fh->fd == -1) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems * to do this call. JRA. */ if (INFO_LEVEL_IS_UNIX(file_info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn, fsp->fsp_name)) { DEBUG(3,("smbd_smb2_getinfo_send: " "SMB_VFS_LSTAT of %s failed " "(%s)\n", fsp_str_dbg(fsp), strerror(errno))); status = map_nt_error_from_unix(errno); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } } else if (SMB_VFS_STAT(conn, fsp->fsp_name)) { DEBUG(3,("smbd_smb2_getinfo_send: " "SMB_VFS_STAT of %s failed (%s)\n", fsp_str_dbg(fsp), strerror(errno))); status = map_nt_error_from_unix(errno); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } fileid = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st); get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts); } else { /* * Original code - this is an open file. */ if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { DEBUG(3, ("smbd_smb2_getinfo_send: " "fstat of %s failed (%s)\n", fsp_fnum_dbg(fsp), strerror(errno))); status = map_nt_error_from_unix(errno); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } fileid = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st); get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts); } status = smbd_do_qfilepathinfo(conn, state, file_info_level, fsp, fsp->fsp_name, delete_pending, write_time_ts, ea_list, lock_data_count, lock_data, STR_UNICODE, in_output_buffer_length, &fixed_portion, &data, &data_size); if (!NT_STATUS_IS_OK(status)) { SAFE_FREE(data); if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { status = NT_STATUS_INVALID_INFO_CLASS; } tevent_req_nterror(req, status); return tevent_req_post(req, ev); } if (in_output_buffer_length < fixed_portion) { SAFE_FREE(data); tevent_req_nterror( req, NT_STATUS_INFO_LENGTH_MISMATCH); return tevent_req_post(req, ev); } if (data_size > 0) { state->out_output_buffer = data_blob_talloc(state, data, data_size); SAFE_FREE(data); if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } if (data_size > in_output_buffer_length) { state->out_output_buffer.length = in_output_buffer_length; status = STATUS_BUFFER_OVERFLOW; } } SAFE_FREE(data); break; } case SMB2_GETINFO_FS: { uint16_t file_info_level; char *data = NULL; int data_size = 0; size_t fixed_portion; /* the levels directly map to the passthru levels */ file_info_level = in_file_info_class + 1000; status = smbd_do_qfsinfo(conn, state, file_info_level, STR_UNICODE, in_output_buffer_length, &fixed_portion, fsp->fsp_name, &data, &data_size); /* some responses set STATUS_BUFFER_OVERFLOW and return partial, but valid data */ if (!(NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW))) { SAFE_FREE(data); if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { status = NT_STATUS_INVALID_INFO_CLASS; } tevent_req_nterror(req, status); return tevent_req_post(req, ev); } if (in_output_buffer_length < fixed_portion) { SAFE_FREE(data); tevent_req_nterror( req, NT_STATUS_INFO_LENGTH_MISMATCH); return tevent_req_post(req, ev); } if (data_size > 0) { state->out_output_buffer = data_blob_talloc(state, data, data_size); SAFE_FREE(data); if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } if (data_size > in_output_buffer_length) { state->out_output_buffer.length = in_output_buffer_length; status = STATUS_BUFFER_OVERFLOW; } } SAFE_FREE(data); break; } case SMB2_GETINFO_SECURITY: { uint8_t *p_marshalled_sd = NULL; size_t sd_size = 0; status = smbd_do_query_security_desc(conn, state, fsp, /* Security info wanted. */ in_additional_information & SMB_SUPPORTED_SECINFO_FLAGS, in_output_buffer_length, &p_marshalled_sd, &sd_size); if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) { /* Return needed size. */ state->out_output_buffer = data_blob_talloc(state, NULL, 4); if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } SIVAL(state->out_output_buffer.data,0,(uint32_t)sd_size); state->status = NT_STATUS_BUFFER_TOO_SMALL; break; } if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("smbd_smb2_getinfo_send: " "smbd_do_query_security_desc of %s failed " "(%s)\n", fsp_str_dbg(fsp), nt_errstr(status))); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } if (sd_size > 0) { state->out_output_buffer = data_blob_talloc(state, p_marshalled_sd, sd_size); if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } } break; } case SMB2_GETINFO_QUOTA: tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); return tevent_req_post(req, ev); default: DEBUG(10,("smbd_smb2_getinfo_send: " "unknown in_info_type of %u " " for file %s\n", (unsigned int)in_info_type, fsp_str_dbg(fsp) )); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } state->status = status; tevent_req_done(req); return tevent_req_post(req, ev); }
/* handle stdout/stderr from the child */ static void samba_runcmd_io_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct tevent_req *req = talloc_get_type_abort(private_data, struct tevent_req); struct samba_runcmd_state *state = tevent_req_data(req, struct samba_runcmd_state); int level; char *p; int n, fd; if (!(flags & TEVENT_FD_READ)) { return; } if (fde == state->fde_stdout) { level = state->stdout_log_level; fd = state->fd_stdout; } else if (fde == state->fde_stderr) { level = state->stderr_log_level; fd = state->fd_stderr; } else { int status; status = tfork_status(&state->tfork, false); if (status == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return; } DBG_ERR("Bad read on status pipe\n"); tevent_req_error(req, errno); return; } state->pid = -1; TALLOC_FREE(fde); if (WIFEXITED(status)) { status = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { status = WTERMSIG(status); } else { status = ECHILD; } DBG_NOTICE("Child %s exited %d\n", state->arg0, status); if (status != 0) { tevent_req_error(req, status); return; } tevent_req_done(req); return; } n = read(fd, &state->buf[state->buf_used], sizeof(state->buf) - state->buf_used); if (n > 0) { state->buf_used += n; } else if (n == 0) { if (fde == state->fde_stdout) { talloc_free(fde); state->fde_stdout = NULL; return; } if (fde == state->fde_stderr) { talloc_free(fde); state->fde_stderr = NULL; return; } return; } while (state->buf_used > 0 && (p = (char *)memchr(state->buf, '\n', state->buf_used)) != NULL) { int n1 = (p - state->buf)+1; int n2 = n1 - 1; /* swallow \r from child processes */ if (n2 > 0 && state->buf[n2-1] == '\r') { n2--; } DEBUG(level,("%s: %*.*s\n", state->arg0, n2, n2, state->buf)); memmove(state->buf, p+1, sizeof(state->buf) - n1); state->buf_used -= n1; } /* the buffer could have completely filled - unfortunately we have no choice but to dump it out straight away */ if (state->buf_used == sizeof(state->buf)) { DEBUG(level,("%s: %*.*s\n", state->arg0, state->buf_used, state->buf_used, state->buf)); state->buf_used = 0; } }
static void cli_trans_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); struct cli_trans_state *state = tevent_req_data( req, struct cli_trans_state); NTSTATUS status; bool sent_all; uint8_t wct; uint16_t *vwv; uint32_t num_bytes; uint8_t *bytes; uint8_t num_setup = 0; uint16_t *setup = NULL; uint32_t total_param = 0; uint32_t num_param = 0; uint32_t param_disp = 0; uint32_t total_data = 0; uint32_t num_data = 0; uint32_t data_disp = 0; uint8_t *param = NULL; uint8_t *data = NULL; status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes); /* * We can receive something like STATUS_MORE_ENTRIES, so don't use * !NT_STATUS_IS_OK(status) here. */ if (NT_STATUS_IS_ERR(status)) { goto fail; } sent_all = ((state->param_sent == state->num_param) && (state->data_sent == state->num_data)); status = cli_pull_trans( cli_smb_inbuf(subreq), wct, vwv, num_bytes, bytes, state->cmd, !sent_all, &num_setup, &setup, &total_param, &num_param, ¶m_disp, ¶m, &total_data, &num_data, &data_disp, &data); if (!NT_STATUS_IS_OK(status)) { goto fail; } if (!sent_all) { int iov_count; TALLOC_FREE(subreq); cli_trans_format(state, &wct, &iov_count); subreq = cli_smb_req_create(state, state->ev, state->cli, state->cmd + 1, 0, wct, state->vwv, iov_count, state->iov); if (tevent_req_nomem(subreq, req)) { return; } cli_smb_req_set_mid(subreq, state->mid); if (!cli_smb_req_send(subreq)) { status = NT_STATUS_NO_MEMORY; goto fail; } tevent_req_set_callback(subreq, cli_trans_done, req); return; } status = cli_trans_pull_blob( state, &state->rparam, total_param, num_param, param, param_disp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status))); goto fail; } status = cli_trans_pull_blob( state, &state->rdata, total_data, num_data, data, data_disp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status))); goto fail; } if ((state->rparam.total == state->rparam.received) && (state->rdata.total == state->rdata.received)) { TALLOC_FREE(subreq); cli_state_seqnum_remove(state->cli, state->mid); tevent_req_done(req); return; } if (!cli_smb_req_set_pending(subreq)) { status = NT_STATUS_NO_MEMORY; goto fail; } return; fail: cli_state_seqnum_remove(state->cli, state->mid); TALLOC_FREE(subreq); tevent_req_nterror(req, status); }
static void smb1cli_trans_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct smb1cli_trans_state *state = tevent_req_data(req, struct smb1cli_trans_state); NTSTATUS status; bool sent_all; struct iovec *recv_iov = NULL; uint8_t *inhdr; uint8_t wct; uint16_t *vwv; uint32_t vwv_ofs; uint32_t num_bytes; uint8_t *bytes; uint32_t bytes_ofs; uint8_t num_setup = 0; uint16_t *setup = NULL; uint32_t total_param = 0; uint32_t num_param = 0; uint32_t param_disp = 0; uint32_t total_data = 0; uint32_t num_data = 0; uint32_t data_disp = 0; uint8_t *param = NULL; uint8_t *data = NULL; status = smb1cli_req_recv(subreq, state, &recv_iov, &inhdr, &wct, &vwv, &vwv_ofs, &num_bytes, &bytes, &bytes_ofs, NULL, /* pinbuf */ NULL, 0); /* expected */ /* * Do not TALLOC_FREE(subreq) here, we might receive more than * one response for the same mid. */ /* * We can receive something like STATUS_MORE_ENTRIES, so don't use * !NT_STATUS_IS_OK(status) here. */ if (NT_STATUS_IS_ERR(status)) { goto fail; } if (recv_iov == NULL) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto fail; } state->status = status; sent_all = ((state->param_sent == state->num_param) && (state->data_sent == state->num_data)); status = smb1cli_pull_trans( inhdr, wct, vwv, vwv_ofs, num_bytes, bytes, bytes_ofs, state->cmd, !sent_all, &num_setup, &setup, &total_param, &num_param, ¶m_disp, ¶m, &total_data, &num_data, &data_disp, &data); if (!NT_STATUS_IS_OK(status)) { goto fail; } if (!sent_all) { int iov_count; struct tevent_req *subreq2; smb1cli_trans_format(state, &wct, &iov_count); subreq2 = smb1cli_req_create(state, state->ev, state->conn, state->cmd + 1, 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(subreq2, req)) { return; } smb1cli_req_set_mid(subreq2, state->mid); status = smb1cli_req_chain_submit(&subreq2, 1); if (!NT_STATUS_IS_OK(status)) { goto fail; } tevent_req_set_callback(subreq2, smb1cli_trans_done2, req); return; } status = smb1cli_trans_pull_blob( state, &state->rparam, total_param, num_param, param, param_disp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status))); goto fail; } status = smb1cli_trans_pull_blob( state, &state->rdata, total_data, num_data, data, data_disp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status))); goto fail; } if ((state->rparam.total == state->rparam.received) && (state->rdata.total == state->rdata.received)) { state->recv_flags2 = SVAL(inhdr, HDR_FLG2); smb1cli_trans_cleanup_primary(state); tevent_req_done(req); return; } TALLOC_FREE(recv_iov); return; fail: smb1cli_trans_cleanup_primary(state); tevent_req_nterror(req, status); }
struct tevent_req *tsocket_writev_send(struct tsocket_context *sock, TALLOC_CTX *mem_ctx, const struct iovec *vector, size_t count) { struct tevent_req *req; struct tsocket_writev_state *state; int ret; int err; bool dummy; int to_write = 0; size_t i; req = tevent_req_create(mem_ctx, &state, struct tsocket_writev_state); if (!req) { return NULL; } state->caller.sock = sock; state->caller.vector = vector; state->caller.count = count; state->iov = NULL; state->count = count; state->total_written = 0; state->iov = talloc_array(state, struct iovec, count); if (tevent_req_nomem(state->iov, req)) { goto post; } memcpy(state->iov, vector, sizeof(struct iovec) * count); for (i=0; i < count; i++) { int tmp = to_write; tmp += state->iov[i].iov_len; if (tmp < to_write) { tevent_req_error(req, EMSGSIZE); goto post; } to_write = tmp; } if (to_write == 0) { tevent_req_done(req); goto post; } /* * this is a fast path, not waiting for the * socket to become explicit writeable gains * about 10%-20% performance in benchmark tests. */ tsocket_writev_handler(sock, req); if (!tevent_req_is_in_progress(req)) { goto post; } talloc_set_destructor(state, tsocket_writev_state_destructor); ret = tsocket_set_writeable_handler(sock, tsocket_writev_handler, req); err = tsocket_error_from_errno(ret, errno, &dummy); if (tevent_req_error(req, err)) { goto post; } return req; post: return tevent_req_post(req, sock->event.ctx); }