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;
}
*/
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;
req->async.callback(req);
}
}
+
+ talloc_set_destructor(conn, NULL);
+ if (conn->free_skipped) {
+ talloc_free(conn);
+ }
}
/*
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);
}
/*
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 *);
/*
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;
talloc_free(smb);
- return NT_STATUS_OK;
+ return status;
}
/*
/*
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;
talloc_free(smb);
- return NT_STATUS_OK;
+ return 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);
}
/*
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;
}
/*
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;
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 */