summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/rpc/dcerpc.c42
-rw-r--r--source4/librpc/rpc/dcerpc.h6
-rw-r--r--source4/librpc/rpc/dcerpc_util.c1
3 files changed, 49 insertions, 0 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 284a3c8841..fa7fe728d4 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -110,6 +110,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx)
p->last_fault_code = 0;
p->context_id = 0;
+ p->request_timeout = DCERPC_REQUEST_TIMEOUT;
ZERO_STRUCT(p->syntax);
ZERO_STRUCT(p->transfer_syntax);
@@ -521,6 +522,17 @@ static void full_request_recv(struct dcerpc_connection *c, DATA_BLOB *blob,
}
/*
+ handle timeouts of full dcerpc requests
+*/
+static void dcerpc_full_timeout_handler(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private)
+{
+ struct full_request_state *state = talloc_get_type(private,
+ struct full_request_state);
+ state->status = NT_STATUS_IO_TIMEOUT;
+}
+
+/*
perform a single pdu synchronous request - used for the bind code
this cannot be mixed with normal async requests
*/
@@ -547,6 +559,10 @@ static NTSTATUS full_request(struct dcerpc_connection *c,
return status;
}
+ event_add_timed(c->transport.event_context(c), state,
+ timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
+ dcerpc_full_timeout_handler, state);
+
while (NT_STATUS_IS_OK(state->status) && state->reply_blob) {
struct event_context *ctx = c->transport.event_context(c);
if (event_loop_once(ctx) != 0) {
@@ -830,6 +846,26 @@ static void dcerpc_request_recv_data(struct dcerpc_connection *c,
}
}
+/*
+ handle timeouts of individual dcerpc requests
+*/
+static void dcerpc_timeout_handler(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private)
+{
+ struct rpc_request *req = talloc_get_type(private, struct rpc_request);
+
+ if (req->state != RPC_REQUEST_PENDING) {
+ return;
+ }
+
+ req->status = NT_STATUS_IO_TIMEOUT;
+ req->state = RPC_REQUEST_DONE;
+ DLIST_REMOVE(req->p->conn->pending, req);
+ if (req->async.callback) {
+ req->async.callback(req);
+ }
+}
+
/*
make sure requests are cleaned up
@@ -932,6 +968,12 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
remaining -= chunk;
}
+ if (p->request_timeout) {
+ event_add_timed(dcerpc_event_context(p), req,
+ timeval_current_ofs(p->request_timeout, 0),
+ dcerpc_timeout_handler, req);
+ }
+
talloc_set_destructor(req, dcerpc_req_destructor);
return req;
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 89a969a118..2f64c0ef34 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -94,8 +94,14 @@ struct dcerpc_pipe {
/* the last fault code from a DCERPC fault */
uint32_t last_fault_code;
+
+ /* timeout for individual rpc requests, in seconds */
+ uint_t request_timeout;
};
+/* default timeout for all rpc requests, in seconds */
+#define DCERPC_REQUEST_TIMEOUT 60
+
/* dcerpc pipe flags */
#define DCERPC_DEBUG_PRINT_IN (1<<0)
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 949b21e68c..8ae7814c26 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -1343,6 +1343,7 @@ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p,
return NT_STATUS_NO_MEMORY;
}
p2->conn = talloc_reference(p2, p->conn);
+ p2->request_timeout = p->request_timeout;
p2->context_id = ++p->conn->next_context_id;