mirror of
https://github.com/samba-team/samba.git
synced 2025-09-17 05:44:20 +03:00
r22470: merge handling of broken connections from wins replication client code
to the rpc client code we need to always ask for read events on the socket otherwise we never get the connection error reported. shutdown the transport when a request timeout. metze
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
d491e60c70
commit
3403c0cb15
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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 *);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user