const struct ndr_syntax_id *abstract_syntax,
struct rpc_cli_transport **presult);
struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p);
+void rpccli_close_np_fd(struct rpc_pipe_client *p);
/* The following definitions come from rpc_client/rpc_transport_smbd.c */
struct rpc_cli_smbd_conn *conn,
const struct ndr_syntax_id *abstract_syntax,
struct rpc_cli_transport **presult);
+struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p);
/* The following definitions come from rpc_client/rpc_transport_sock.c */
NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
struct rpc_cli_transport **presult);
+int rpccli_set_sock_timeout(struct rpc_pipe_client *rpccli, int timeout);
+void rpccli_close_sock_fd(struct rpc_pipe_client *rpccli);
+bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *rpccli);
/* The following definitions come from rpc_client/cli_samr.c */
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])
}
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;
}
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;
+}
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;
+}
struct rpc_transport_sock_state {
int fd;
+ int timeout;
};
static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s)
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) {
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:
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) {
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:
result->priv = state;
state->fd = fd;
+ state->timeout = 10000; /* 10 seconds. */
talloc_set_destructor(state, rpc_transport_sock_state_destructor);
result->trans_send = NULL;
*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;
+}
if (conn->lsa_pipe_tcp &&
conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
- conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+ conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
+ rpc_pipe_tcp_connection_ok(conn->lsa_pipe_tcp)) {
goto done;
}
* This call can take a long time
* allow the server to time out.
* 35 seconds should do it.
- * NB
- * only do this when the undelying transport is named pipe.
*/
- if (cli->transport->transport == NCACN_NP) {
- orig_timeout = rpccli_set_timeout(cli, 35000);
- }
+ orig_timeout = rpccli_set_timeout(cli, 35000);
status = lookup_names_fn(cli,
mem_ctx,
types);
/* And restore our original timeout. */
- if (cli->transport->transport == NCACN_NP) {
- rpccli_set_timeout(cli, orig_timeout);
- }
+ rpccli_set_timeout(cli, orig_timeout);
if (!NT_STATUS_IS_OK(status)) {
return status;