Пример #1
0
/*
  setup a handler for incoming requests
*/
NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c,
				    void (*handler)(struct cldap_socket *,
						    void *private_data,
						    struct cldap_incoming *),
				    void *private_data)
{
	if (c->connected) {
		return NT_STATUS_PIPE_CONNECTED;
	}

	/* if sync requests are allowed, we don't allow an incoming handler */
	if (c->event.allow_poll) {
		return NT_STATUS_INVALID_PIPE_STATE;
	}

	c->incoming.handler = handler;
	c->incoming.private_data = private_data;

	if (!cldap_recvfrom_setup(c)) {
		ZERO_STRUCT(c->incoming);
		return NT_STATUS_NO_MEMORY;
	}

	return NT_STATUS_OK;
}
Пример #2
0
static void cldap_recvfrom_done(struct tevent_req *subreq)
{
	struct cldap_socket *c = tevent_req_callback_data(subreq,
				 struct cldap_socket);
	struct cldap_incoming *in = NULL;
	ssize_t ret;

	c->recv_subreq = NULL;

	in = talloc_zero(c, struct cldap_incoming);
	if (!in) {
		goto nomem;
	}

	ret = tdgram_recvfrom_recv(subreq,
				   &in->recv_errno,
				   in,
				   &in->buf,
				   &in->src);
	talloc_free(subreq);
	subreq = NULL;
	if (ret >= 0) {
		in->len = ret;
	}
	if (ret == -1 && in->recv_errno == 0) {
		in->recv_errno = EIO;
	}

	/* this function should free or steal 'in' */
	cldap_socket_recv_dgram(c, in);
	in = NULL;

	if (!cldap_recvfrom_setup(c)) {
		goto nomem;
	}

	return;

nomem:
	talloc_free(subreq);
	talloc_free(in);
	/*TODO: call a dead socket handler */
	return;
}
Пример #3
0
/*
  setup a handler for incoming requests
*/
NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c,
				    struct tevent_context *ev,
				    void (*handler)(struct cldap_socket *,
						    void *private_data,
						    struct cldap_incoming *),
				    void *private_data)
{
	if (c->connected) {
		return NT_STATUS_PIPE_CONNECTED;
	}

	c->incoming.ev = ev;
	c->incoming.handler = handler;
	c->incoming.private_data = private_data;

	if (!cldap_recvfrom_setup(c)) {
		ZERO_STRUCT(c->incoming);
		return NT_STATUS_NO_MEMORY;
	}

	return NT_STATUS_OK;
}
Пример #4
0
/*
  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;
}