diff options
author | Bo Yang <boyang@samba.org> | 2010-01-06 12:13:35 +0800 |
---|---|---|
committer | Bo Yang <boyang@samba.org> | 2010-01-06 19:19:35 +0800 |
commit | 36493bf2f6634b84c57107bcb86bcbf3e82e80fc (patch) | |
tree | 3cb21abc0fca7550f7a4b6185769a84217e9b0d2 /source3/rpc_client | |
parent | da41f23bdad1ea3a1a49110217cfde3efcde5075 (diff) | |
download | samba-36493bf2f6634b84c57107bcb86bcbf3e82e80fc.tar.gz samba-36493bf2f6634b84c57107bcb86bcbf3e82e80fc.tar.bz2 samba-36493bf2f6634b84c57107bcb86bcbf3e82e80fc.zip |
s3: Fix infinite loop in NCACN_IP_TCP asa there is no timeout. Assume lsa_pipe_tcp is ok but network is down, then send request is ok, but select() on writeable fds loops forever since there is no response.
Signed-off-by: Bo Yang <boyang@samba.org>
Diffstat (limited to 'source3/rpc_client')
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 26 | ||||
-rw-r--r-- | source3/rpc_client/ndr.c | 15 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_np.c | 12 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_smbd.c | 10 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_sock.c | 53 |
5 files changed, 112 insertions, 4 deletions
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 96531666d5..48e2f9eb51 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3035,12 +3035,30 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli, unsigned int timeout) { - struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli); + struct cli_state *cli; - if (cli == NULL) { - return 0; + if (rpc_cli->transport->transport == NCACN_NP) { + cli = rpc_pipe_np_smb_conn(rpc_cli); + if (cli == NULL) { + return 0; + } + return cli_set_timeout(cli, timeout); + } + + if (rpc_cli->transport->transport == NCACN_IP_TCP || + rpc_cli->transport->transport == NCALRPC) { + return rpccli_set_sock_timeout(rpc_cli, timeout); } - return cli_set_timeout(cli, timeout); + + if (rpc_cli->transport->transport == NCACN_INTERNAL) { + cli = rpc_pipe_smbd_smb_conn(rpc_cli); + if (!cli) { + return 0; + } + return cli_set_timeout(cli, timeout); + } + + return 0; } bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16]) diff --git a/source3/rpc_client/ndr.c b/source3/rpc_client/ndr.c index 6433a7d196..4e8634d3b9 100644 --- a/source3/rpc_client/ndr.c +++ b/source3/rpc_client/ndr.c @@ -182,6 +182,21 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, } status = cli_do_rpc_ndr_recv(req, mem_ctx); + + /* + * NT_STATUS_IO_TIMEOUT indicates network problem, + * tear the connection apart. + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + if (cli->transport->transport == NCACN_IP_TCP || + cli->transport->transport == NCALRPC) { + rpccli_close_sock_fd(cli); + } + + if (cli->transport->transport == NCACN_NP) { + rpccli_close_np_fd(cli); + } + } fail: TALLOC_FREE(frame); return status; diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index de748d9bbc..9f8872c467 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -402,3 +402,15 @@ struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p) } return state->cli; } + +void rpccli_close_np_fd(struct rpc_pipe_client *p) +{ + struct cli_state *cli = rpc_pipe_np_smb_conn(p); + if (cli) { + if (cli->fd != -1) { + close(cli->fd); + cli->fd = -1; + } + } + return; +} diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 171048ae29..929e553c84 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -682,3 +682,13 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx, TALLOC_FREE(frame); return status; } + +struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p) +{ + struct rpc_transport_smbd_state *state = talloc_get_type(p->transport->priv, + struct rpc_transport_smbd_state); + if (!state || !state->conn) { + return NULL; + } + return state->conn->cli; +} diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index 4ab6500900..df060e61e9 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -24,6 +24,7 @@ struct rpc_transport_sock_state { int fd; + int timeout; }; static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s) @@ -51,6 +52,7 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_sock_state); struct tevent_req *req, *subreq; struct rpc_sock_read_state *state; + struct timeval endtime; req = tevent_req_create(mem_ctx, &state, struct rpc_sock_read_state); if (req == NULL) { @@ -61,10 +63,16 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } state->transp = sock_transp; + endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; } + + if (!tevent_req_set_endtime(subreq, ev, endtime)) { + goto fail; + } + tevent_req_set_callback(subreq, rpc_sock_read_done, req); return req; fail: @@ -121,6 +129,7 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_sock_state); struct tevent_req *req, *subreq; struct rpc_sock_write_state *state; + struct timeval endtime; req = tevent_req_create(mem_ctx, &state, struct rpc_sock_write_state); if (req == NULL) { @@ -131,10 +140,16 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } state->transp = sock_transp; + endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; } + + if (!tevent_req_set_endtime(subreq, ev, endtime)) { + goto fail; + } + tevent_req_set_callback(subreq, rpc_sock_write_done, req); return req; fail: @@ -193,6 +208,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, result->priv = state; state->fd = fd; + state->timeout = 10000; /* 10 seconds. */ talloc_set_destructor(state, rpc_transport_sock_state_destructor); result->trans_send = NULL; @@ -205,3 +221,40 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, *presult = result; return NT_STATUS_OK; } + +int rpccli_set_sock_timeout(struct rpc_pipe_client *cli, int timeout) +{ + struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv, + struct rpc_transport_sock_state); + int orig_timeout; + if (!state) { + return 0; + } + orig_timeout = state->timeout; + state->timeout = timeout; + return orig_timeout; +} + +void rpccli_close_sock_fd(struct rpc_pipe_client *cli) +{ + struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv, + struct rpc_transport_sock_state); + if (state) { + if (state->fd != -1) { + close(state->fd); + state->fd = -1; + } + } + return; +} + +bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *cli) +{ + struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv, + struct rpc_transport_sock_state); + if (state && state->fd != -1) { + return true; + } + + return false; +} |