diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 35 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 5 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb.c | 6 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb2.c | 6 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_sock.c | 33 |
5 files changed, 57 insertions, 28 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 820516ba11..79e897313d 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -37,14 +37,17 @@ NTSTATUS dcerpc_init(void) return NT_STATUS_OK; } +static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status); static void dcerpc_ship_next_request(struct dcerpc_connection *c); /* destroy a dcerpc connection */ -static int dcerpc_connection_destructor(struct dcerpc_connection *c) +static int dcerpc_connection_destructor(struct dcerpc_connection *conn) { - if (c->transport.shutdown_pipe) { - c->transport.shutdown_pipe(c); + if (conn->dead) { + conn->free_skipped = True; + return -1; } + dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT); return 0; } @@ -553,6 +556,14 @@ static int dcerpc_req_dequeue(struct rpc_request *req) */ static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status) { + if (conn->dead) return; + + conn->dead = true; + + if (conn->transport.shutdown_pipe) { + conn->transport.shutdown_pipe(conn, status); + } + /* all pending requests get the error */ while (conn->pending) { struct rpc_request *req = conn->pending; @@ -563,6 +574,11 @@ static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS stat req->async.callback(req); } } + + talloc_set_destructor(conn, NULL); + if (conn->free_skipped) { + talloc_free(conn); + } } /* @@ -657,18 +673,7 @@ static void dcerpc_timeout_handler(struct event_context *ev, struct timed_event struct timeval t, void *private) { struct rpc_request *req = talloc_get_type(private, struct rpc_request); - - if (req->state == RPC_REQUEST_DONE) { - return; - } - - dcerpc_req_dequeue(req); - - req->status = NT_STATUS_IO_TIMEOUT; - req->state = RPC_REQUEST_DONE; - if (req->async.callback) { - req->async.callback(req); - } + dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT); } /* diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 8fed56584d..c6dbc35477 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -57,11 +57,14 @@ struct dcerpc_connection { const char *binding_string; struct event_context *event_ctx; + bool dead; + bool free_skipped; + struct dcerpc_transport { enum dcerpc_transport_t transport; void *private; - NTSTATUS (*shutdown_pipe)(struct dcerpc_connection *); + NTSTATUS (*shutdown_pipe)(struct dcerpc_connection *, NTSTATUS status); const char *(*peer_name)(struct dcerpc_connection *); diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index d6d2cf0dfb..55fc37d84f 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -326,14 +326,14 @@ static NTSTATUS smb_send_request(struct dcerpc_connection *c, DATA_BLOB *blob, B /* shutdown SMB pipe connection */ -static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c) +static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c, NTSTATUS status) { struct smb_private *smb = c->transport.private; union smb_close io; struct smbcli_request *req; /* maybe we're still starting up */ - if (!smb) return NT_STATUS_OK; + if (!smb) return status; io.close.level = RAW_CLOSE_CLOSE; io.close.in.file.fnum = smb->fnum; @@ -346,7 +346,7 @@ static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c) talloc_free(smb); - return NT_STATUS_OK; + return status; } /* diff --git a/source4/librpc/rpc/dcerpc_smb2.c b/source4/librpc/rpc/dcerpc_smb2.c index 20d1c7c211..d2ab47898e 100644 --- a/source4/librpc/rpc/dcerpc_smb2.c +++ b/source4/librpc/rpc/dcerpc_smb2.c @@ -299,14 +299,14 @@ static NTSTATUS smb2_send_request(struct dcerpc_connection *c, DATA_BLOB *blob, /* shutdown SMB pipe connection */ -static NTSTATUS smb2_shutdown_pipe(struct dcerpc_connection *c) +static NTSTATUS smb2_shutdown_pipe(struct dcerpc_connection *c, NTSTATUS status) { struct smb2_private *smb = c->transport.private; struct smb2_close io; struct smb2_request *req; /* maybe we're still starting up */ - if (!smb) return NT_STATUS_OK; + if (!smb) return status; ZERO_STRUCT(io); io.in.file.handle = smb->handle; @@ -318,7 +318,7 @@ static NTSTATUS smb2_shutdown_pipe(struct dcerpc_connection *c) talloc_free(smb); - return NT_STATUS_OK; + return status; } /* diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c index ae7d00b669..fd54a20afc 100644 --- a/source4/librpc/rpc/dcerpc_sock.c +++ b/source4/librpc/rpc/dcerpc_sock.c @@ -48,12 +48,34 @@ static void sock_dead(struct dcerpc_connection *p, NTSTATUS status) { struct sock_private *sock = p->transport.private; - if (sock && sock->sock != NULL) { + if (!sock) return; + + if (sock->fde) { + talloc_free(sock->fde); + sock->fde = NULL; + } + + if (sock->sock) { talloc_free(sock->fde); + sock->fde = NULL; talloc_free(sock->sock); sock->sock = NULL; } + if (sock->packet) { + packet_recv_disable(sock->packet); + packet_set_fde(sock->packet, NULL); + packet_set_socket(sock->packet, NULL); + } + + if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) { + status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; + } + + if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) { + status = NT_STATUS_END_OF_FILE; + } + if (!NT_STATUS_IS_OK(status)) { p->transport.recv_data(p, NULL, status); } @@ -172,15 +194,15 @@ static NTSTATUS sock_send_request(struct dcerpc_connection *p, DATA_BLOB *data, /* shutdown sock pipe connection */ -static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p) +static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p, NTSTATUS status) { struct sock_private *sock = p->transport.private; if (sock && sock->sock) { - sock_dead(p, NT_STATUS_OK); + sock_dead(p, status); } - return NT_STATUS_OK; + return status; } /* @@ -253,7 +275,7 @@ static void continue_socket_connect(struct composite_context *ctx) sock->server_name = strupper_talloc(sock, s->target_hostname); sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock), - 0, sock_io_handler, conn); + EVENT_FD_READ, sock_io_handler, conn); conn->transport.private = sock; @@ -272,7 +294,6 @@ static void continue_socket_connect(struct composite_context *ctx) packet_set_event_context(sock->packet, conn->event_ctx); packet_set_fde(sock->packet, sock->fde); packet_set_serialise(sock->packet); - packet_recv_disable(sock->packet); packet_set_initial_read(sock->packet, 16); /* ensure we don't get SIGPIPE */ |