bool verify_pcontext;
bool cancelled;
struct tevent_req *cancel_subreq;
- bool orphaned;
- struct tevent_req *orphaned_subreq;
- uint32_t orphaned_generation;
struct {
void (*callback)(struct rpc_request *);
struct dcerpc_pipe *p,
uint32_t call_id);
static NTSTATUS dcerpc_submit_cancel_recv(struct tevent_req *req);
-static struct tevent_req *dcerpc_submit_orphaned_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct dcerpc_pipe *p,
- uint32_t call_id);
-static NTSTATUS dcerpc_submit_orphaned_recv(struct tevent_req *req);
/* destroy a dcerpc connection */
static int dcerpc_connection_destructor(struct dcecli_connection *conn)
static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
static bool dcerpc_bh_raw_call_cancel(struct tevent_req *req);
-static void dcerpc_bh_raw_call_cleanup(struct tevent_req *req,
- enum tevent_req_state req_state);
static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
state->subreq->async.private_data = req;
tevent_req_set_cancel_fn(req, dcerpc_bh_raw_call_cancel);
- tevent_req_set_cleanup_fn(req, dcerpc_bh_raw_call_cleanup);
return req;
}
subreq->cancelled = true;
}
-static void dcerpc_bh_raw_call_orphaned(struct tevent_req *orphaned_subreq);
-static void dcerpc_bh_raw_call_orphaned_cancelled(
- struct tevent_req *cancel_subreq);
-static void dcerpc_bh_raw_call_free(struct rpc_request *subreq);
-
-static void dcerpc_bh_raw_call_cleanup(struct tevent_req *req,
- enum tevent_req_state req_state)
-{
- struct dcerpc_bh_raw_call_state *state =
- tevent_req_data(req, struct dcerpc_bh_raw_call_state);
- struct rpc_request *subreq = state->subreq;
-
- if (req_state != TEVENT_REQ_RECEIVED) {
- return;
- }
-
- switch (subreq->state) {
- case RPC_REQUEST_DONE:
- /* Nothing to do */
- return;
- case RPC_REQUEST_QUEUED:
- {
- /* Nothing to do, the rpc_request destructor will dequeue */
- return;
- }
- case RPC_REQUEST_PENDING:
- {
- /* Send orphaned or cancel PDU */
- break;
- }
- }
-
- if (subreq->p->conn->bind_time_features &
- DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
- subreq->orphaned_subreq = dcerpc_submit_orphaned_send(
- subreq,
- state->ev,
- subreq->p,
- subreq->call_id);
- if (subreq->orphaned_subreq == NULL) {
- DBG_ERR("No memory\n");
- return;
- }
- tevent_req_set_callback(subreq->orphaned_subreq,
- dcerpc_bh_raw_call_orphaned,
- subreq);
-
- /*
- * As req will be free when returning from this function
- * move the subreq to the pipe talloc context and reset
- * the callback to a function that just frees.
- */
- subreq->async.callback = dcerpc_bh_raw_call_free;
- subreq->async.private_data = NULL;
- talloc_move(subreq->p, &subreq);
- return;
- }
-
- /* Fallback to co_cancel if co_orphan can't be used */
-
- if (subreq->cancelled) {
- /* co_cancel is already submitted */
- return;
- }
-
- subreq->cancel_subreq = dcerpc_submit_cancel_send(subreq,
- state->ev,
- subreq->p,
- subreq->call_id);
- if (subreq->cancel_subreq == NULL) {
- DBG_ERR("No memory\n");
- return;
- }
- tevent_req_set_callback(subreq->cancel_subreq,
- dcerpc_bh_raw_call_orphaned_cancelled,
- subreq);
- subreq->async.callback = dcerpc_bh_raw_call_free;
- subreq->async.private_data = NULL;
- talloc_move(subreq->p, &subreq);
-}
-
-static void dcerpc_bh_raw_call_orphaned(struct tevent_req *orphaned_subreq)
-{
- struct rpc_request *subreq = tevent_req_callback_data(
- orphaned_subreq, struct rpc_request);
- NTSTATUS status;
-
- status = dcerpc_submit_orphaned_recv(subreq->orphaned_subreq);
- TALLOC_FREE(subreq->orphaned_subreq);
- if (!NT_STATUS_IS_OK(status)) {
- DBG_NOTICE("Failed to send orphaned PDU for call_id %u: "
- "%s\n", subreq->call_id, nt_errstr(status));
- return;
- }
-
- subreq->orphaned = true;
- subreq->orphaned_generation = subreq->p->conn->call_id;
-}
-
-static void dcerpc_bh_raw_call_orphaned_cancelled(
- struct tevent_req *cancel_subreq)
-{
- struct rpc_request *subreq = tevent_req_callback_data(
- cancel_subreq, struct rpc_request);
- NTSTATUS status;
-
- status = dcerpc_submit_orphaned_recv(subreq->cancel_subreq);
- TALLOC_FREE(subreq->cancel_subreq);
- if (!NT_STATUS_IS_OK(status)) {
- DBG_NOTICE("Failed to send cancel PDU for call_id %u: "
- "%s\n", subreq->call_id, nt_errstr(status));
- return;
- }
-
- subreq->cancelled = true;
- subreq->orphaned_generation = subreq->p->conn->call_id;
-}
-
-static void dcerpc_bh_raw_call_free(struct rpc_request *subreq)
-{
- TALLOC_FREE(subreq);
-}
-
static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
{
struct tevent_req *req =
return NT_STATUS_OK;
}
-/*
- * Finds a pending rpc_request in the pending calls list and frees
- * stale orphaned rpc_requests.
- */
-static struct rpc_request *dcerpc_find_pending_request(
- struct dcecli_connection *c,
- uint32_t call_id)
-{
- struct rpc_request *req = NULL;
- struct rpc_request *it = NULL;
- struct rpc_request *free = NULL;
-
- for (it = c->pending; it != NULL; it = it->next) {
- /*
- * If the request is orphaned and we got a response to a
- * request that started after we submitted the co_cancel
- * or co_orphan PDUs then queue for free
- */
- if (it->orphaned_generation != 0 &&
- it->orphaned_generation < call_id) {
- DLIST_ADD(free, it);
- continue;
- }
-
- if (it->call_id == call_id) {
- req = it;
- }
- }
-
- while (free != NULL) {
- it = free;
- DLIST_REMOVE(free, it);
- TALLOC_FREE(it);
- }
-
- return req;
-}
/*
process a fragment received from the transport layer during a
}
/* find the matching request */
- req = dcerpc_find_pending_request(c, pkt->call_id);
+ for (req=c->pending;req;req=req->next) {
+ if (pkt->call_id == req->call_id) break;
+ }
#if 0
/* useful for testing certain vendors RPC servers */
static void dcerpc_writev_orphaned_done(struct tevent_req *subreq);
+_UNUSED_
static struct tevent_req *dcerpc_submit_orphaned_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct dcerpc_pipe *p,
tevent_req_done(req);
}
+_UNUSED_
static NTSTATUS dcerpc_submit_orphaned_recv(struct tevent_req *req)
{
return tevent_req_simple_recv_ntstatus(req);