Exemple #1
0
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));
}
Exemple #2
0
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;
        }
    }
}
Exemple #4
0
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);
}
Exemple #6
0
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);
}
Exemple #7
0
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);
}
Exemple #8
0
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);
	}
}
Exemple #9
0
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);
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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, 
}
Exemple #13
0
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);
}
Exemple #14
0
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);
}
Exemple #15
0
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);
}
Exemple #16
0
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);
}
Exemple #17
0
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);
}
Exemple #18
0
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);
}
Exemple #19
0
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);
}
Exemple #20
0
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);
}
Exemple #21
0
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);
}
Exemple #22
0
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);
}
Exemple #23
0
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;
}
Exemple #26
0
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);
}
Exemple #27
0
/*
  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;
	}
}
Exemple #28
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, &param_disp, &param,
		&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);
}
Exemple #29
0
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, &param_disp, &param,
		&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);
}
Exemple #30
0
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);
}