samba-tool: Fix enum values in dns.py
[Samba.git] / source3 / rpc_client / rpc_transport_np.c
blobf0696adbcc74e57ddcd6871ad2ba296731a33345
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC client transport over named pipes
4 * Copyright (C) Volker Lendecke 2009
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "../lib/util/tevent_ntstatus.h"
22 #include "rpc_client/rpc_transport.h"
23 #include "libsmb/cli_np_tstream.h"
24 #include "client.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_CLI
29 struct rpc_transport_np_init_state {
30 struct rpc_cli_transport *transport;
31 int retries;
32 struct tevent_context *ev;
33 struct cli_state *cli;
34 struct timeval abs_timeout;
35 const char *pipe_name;
38 static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq);
40 struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
41 struct tevent_context *ev,
42 struct cli_state *cli,
43 const struct ndr_syntax_id *abstract_syntax)
45 struct tevent_req *req;
46 struct rpc_transport_np_init_state *state;
47 struct tevent_req *subreq;
49 req = tevent_req_create(mem_ctx, &state,
50 struct rpc_transport_np_init_state);
51 if (req == NULL) {
52 return NULL;
55 state->ev = ev;
56 state->cli = cli;
57 state->abs_timeout = timeval_current_ofs_msec(cli->timeout);
58 state->pipe_name = get_pipe_name_from_syntax(state, abstract_syntax);
59 if (tevent_req_nomem(state->pipe_name, req)) {
60 return tevent_req_post(req, ev);
63 while (state->pipe_name[0] == '\\') {
64 state->pipe_name++;
67 subreq = tstream_cli_np_open_send(state, ev, cli, state->pipe_name);
68 if (tevent_req_nomem(subreq, req)) {
69 return tevent_req_post(req, ev);
71 tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req);
73 return req;
76 static void rpc_transport_np_init_pipe_open_retry(struct tevent_context *ev,
77 struct tevent_timer *te,
78 struct timeval t,
79 void *priv_data)
81 struct tevent_req *subreq;
82 struct tevent_req *req = talloc_get_type(priv_data, struct tevent_req);
83 struct rpc_transport_np_init_state *state = tevent_req_data(
84 req, struct rpc_transport_np_init_state);
86 subreq = tstream_cli_np_open_send(state, ev, state->cli,
87 state->pipe_name);
88 if (tevent_req_nomem(subreq, req)) {
89 return;
91 tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req);
92 state->retries++;
95 static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq)
97 struct tevent_req *req = tevent_req_callback_data(
98 subreq, struct tevent_req);
99 struct rpc_transport_np_init_state *state = tevent_req_data(
100 req, struct rpc_transport_np_init_state);
101 NTSTATUS status;
102 struct tstream_context *stream;
104 status = tstream_cli_np_open_recv(subreq, state, &stream);
105 TALLOC_FREE(subreq);
106 if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_NOT_AVAILABLE)
107 && (!timeval_expired(&state->abs_timeout))) {
108 struct tevent_timer *te;
110 * Retry on STATUS_PIPE_NOT_AVAILABLE, Windows starts some
111 * servers (FssagentRpc) on demand.
113 DEBUG(2, ("RPC pipe %s not available, retry %d\n",
114 state->pipe_name, state->retries));
115 te = tevent_add_timer(state->ev, state,
116 timeval_current_ofs_msec(100 * state->retries),
117 rpc_transport_np_init_pipe_open_retry, req);
118 if (tevent_req_nomem(te, req)) {
119 return;
121 return;
122 } else if (!NT_STATUS_IS_OK(status)) {
123 tevent_req_nterror(req, status);
124 return;
127 status = rpc_transport_tstream_init(state,
128 &stream,
129 &state->transport);
130 if (!NT_STATUS_IS_OK(status)) {
131 tevent_req_nterror(req, status);
132 return;
135 tevent_req_done(req);
138 NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req,
139 TALLOC_CTX *mem_ctx,
140 struct rpc_cli_transport **presult)
142 struct rpc_transport_np_init_state *state = tevent_req_data(
143 req, struct rpc_transport_np_init_state);
144 NTSTATUS status;
146 if (tevent_req_is_nterror(req, &status)) {
147 return status;
150 *presult = talloc_move(mem_ctx, &state->transport);
151 return NT_STATUS_OK;
154 NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
155 const struct ndr_syntax_id *abstract_syntax,
156 struct rpc_cli_transport **presult)
158 TALLOC_CTX *frame = talloc_stackframe();
159 struct tevent_context *ev;
160 struct tevent_req *req;
161 NTSTATUS status = NT_STATUS_OK;
163 ev = samba_tevent_context_init(frame);
164 if (ev == NULL) {
165 status = NT_STATUS_NO_MEMORY;
166 goto fail;
169 req = rpc_transport_np_init_send(frame, ev, cli, abstract_syntax);
170 if (req == NULL) {
171 status = NT_STATUS_NO_MEMORY;
172 goto fail;
175 if (!tevent_req_poll(req, ev)) {
176 status = map_nt_error_from_unix(errno);
177 goto fail;
180 status = rpc_transport_np_init_recv(req, mem_ctx, presult);
181 fail:
182 TALLOC_FREE(frame);
183 return status;