summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2007-04-22 23:00:22 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:51:29 -0500
commit1912124dbfc501c5109f6ac36e125406078d408c (patch)
treea863846bd767627125f22abd26be74db66d81664
parentcc5ad07d84df94f8f2bc16fcb8015f1cf843c1e3 (diff)
downloadsamba-1912124dbfc501c5109f6ac36e125406078d408c.tar.gz
samba-1912124dbfc501c5109f6ac36e125406078d408c.tar.bz2
samba-1912124dbfc501c5109f6ac36e125406078d408c.zip
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 used to be commit 3403c0cb15e08ec838b0bc834f941051fb94d124)
-rw-r--r--source4/librpc/rpc/dcerpc.c35
-rw-r--r--source4/librpc/rpc/dcerpc.h5
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c6
-rw-r--r--source4/librpc/rpc/dcerpc_smb2.c6
-rw-r--r--source4/librpc/rpc/dcerpc_sock.c33
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 */