2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Largely re-written : 2005
6 * Copyright (C) Jeremy Allison 1998 - 2005
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "fake_file.h"
26 #include "rpc_server/rpc_ncacn_np.h"
27 #include "rpc_server/srv_pipe_hnd.h"
28 #include "rpc_server/srv_pipe.h"
29 #include "rpc_server/rpc_server.h"
30 #include "rpc_server/rpc_config.h"
31 #include "../lib/tsocket/tsocket.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "librpc/ndr/ndr_table.h"
36 #define DBGC_CLASS DBGC_RPC_SRV
38 bool fsp_is_np(struct files_struct *fsp)
40 enum FAKE_FILE_TYPE type;
42 if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
46 type = fsp->fake_file_handle->type;
48 return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
51 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
52 const struct tsocket_address *remote_client_address,
53 const struct tsocket_address *local_server_address,
54 struct auth_session_info *session_info,
55 struct tevent_context *ev_ctx,
56 struct messaging_context *msg_ctx,
57 struct fake_file_handle **phandle)
59 enum rpc_service_mode_e pipe_mode;
60 const char **proxy_list;
61 struct fake_file_handle *handle;
62 struct ndr_syntax_id syntax;
63 struct npa_state *npa = NULL;
67 proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
69 handle = talloc(mem_ctx, struct fake_file_handle);
71 return NT_STATUS_NO_MEMORY;
74 /* Check what is the server type for this pipe.
75 Defaults to "embedded" */
76 pipe_mode = rpc_service_mode(name);
78 /* Still support the old method for defining external servers */
79 if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
80 pipe_mode = RPC_SERVICE_MODE_EXTERNAL;
84 case RPC_SERVICE_MODE_EXTERNAL:
85 status = make_external_rpc_pipe(handle,
87 remote_client_address,
91 if (!NT_STATUS_IS_OK(status)) {
96 handle->private_data = (void *)npa;
97 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
100 case RPC_SERVICE_MODE_EMBEDDED:
101 /* Check if we handle this pipe internally */
102 ok = is_known_pipename(name, &syntax);
104 DEBUG(2, ("'%s' is not a registered pipe!\n", name));
106 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
109 status = make_internal_rpc_pipe_socketpair(
115 remote_client_address,
116 local_server_address,
119 if (!NT_STATUS_IS_OK(status)) {
124 handle->private_data = (void *)npa;
125 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
128 case RPC_SERVICE_MODE_DISABLED:
130 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
138 bool np_read_in_progress(struct fake_file_handle *handle)
140 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
141 struct npa_state *p =
142 talloc_get_type_abort(handle->private_data,
146 read_count = tevent_queue_length(p->read_queue);
147 if (read_count > 0) {
157 struct np_write_state {
158 struct tevent_context *ev;
164 static void np_write_done(struct tevent_req *subreq);
166 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
167 struct fake_file_handle *handle,
168 const uint8_t *data, size_t len)
170 struct tevent_req *req;
171 struct np_write_state *state;
174 DEBUG(6, ("np_write_send: len: %d\n", (int)len));
175 dump_data(50, data, len);
177 req = tevent_req_create(mem_ctx, &state, struct np_write_state);
184 status = NT_STATUS_OK;
188 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
189 struct npa_state *p = talloc_get_type_abort(
190 handle->private_data, struct npa_state);
191 struct tevent_req *subreq;
195 state->iov.iov_base = discard_const_p(void, data);
196 state->iov.iov_len = len;
198 subreq = tstream_writev_queue_send(state, ev,
202 if (subreq == NULL) {
205 tevent_req_set_callback(subreq, np_write_done, req);
209 status = NT_STATUS_INVALID_HANDLE;
211 if (NT_STATUS_IS_OK(status)) {
212 tevent_req_done(req);
214 tevent_req_nterror(req, status);
216 return tevent_req_post(req, ev);
222 static void np_write_done(struct tevent_req *subreq)
224 struct tevent_req *req = tevent_req_callback_data(
225 subreq, struct tevent_req);
226 struct np_write_state *state = tevent_req_data(
227 req, struct np_write_state);
231 received = tstream_writev_queue_recv(subreq, &err);
233 tevent_req_nterror(req, map_nt_error_from_unix(err));
236 state->nwritten = received;
237 tevent_req_done(req);
240 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
242 struct np_write_state *state = tevent_req_data(
243 req, struct np_write_state);
246 if (tevent_req_is_nterror(req, &status)) {
249 *pnwritten = state->nwritten;
253 struct np_ipc_readv_next_vector_state {
260 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
261 uint8_t *buf, size_t len)
266 s->len = MIN(len, UINT16_MAX);
269 static int np_ipc_readv_next_vector(struct tstream_context *stream,
272 struct iovec **_vector,
275 struct np_ipc_readv_next_vector_state *state =
276 (struct np_ipc_readv_next_vector_state *)private_data;
277 struct iovec *vector;
281 if (state->ofs == state->len) {
287 pending = tstream_pending_bytes(stream);
292 if (pending == 0 && state->ofs != 0) {
293 /* return a short read */
300 /* we want at least one byte and recheck again */
303 size_t missing = state->len - state->ofs;
304 if (pending > missing) {
305 /* there's more available */
306 state->remaining = pending - missing;
309 /* read what we can get and recheck in the next cycle */
314 vector = talloc_array(mem_ctx, struct iovec, 1);
319 vector[0].iov_base = state->buf + state->ofs;
320 vector[0].iov_len = wanted;
322 state->ofs += wanted;
329 struct np_read_state {
331 struct np_ipc_readv_next_vector_state next_vector;
334 bool is_data_outstanding;
337 static void np_read_done(struct tevent_req *subreq);
339 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
340 struct fake_file_handle *handle,
341 uint8_t *data, size_t len)
343 struct tevent_req *req;
344 struct np_read_state *state;
347 req = tevent_req_create(mem_ctx, &state, struct np_read_state);
352 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
353 struct npa_state *p = talloc_get_type_abort(
354 handle->private_data, struct npa_state);
355 struct tevent_req *subreq;
357 np_ipc_readv_next_vector_init(&state->next_vector,
360 subreq = tstream_readv_pdu_queue_send(state,
364 np_ipc_readv_next_vector,
365 &state->next_vector);
366 if (subreq == NULL) {
367 status = NT_STATUS_NO_MEMORY;
370 tevent_req_set_callback(subreq, np_read_done, req);
374 status = NT_STATUS_INVALID_HANDLE;
376 if (NT_STATUS_IS_OK(status)) {
377 tevent_req_done(req);
379 tevent_req_nterror(req, status);
381 return tevent_req_post(req, ev);
384 static void np_read_done(struct tevent_req *subreq)
386 struct tevent_req *req = tevent_req_callback_data(
387 subreq, struct tevent_req);
388 struct np_read_state *state = tevent_req_data(
389 req, struct np_read_state);
393 ret = tstream_readv_pdu_queue_recv(subreq, &err);
396 tevent_req_nterror(req, map_nt_error_from_unix(err));
401 state->is_data_outstanding = (state->next_vector.remaining > 0);
403 tevent_req_done(req);
407 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
408 bool *is_data_outstanding)
410 struct np_read_state *state = tevent_req_data(
411 req, struct np_read_state);
414 if (tevent_req_is_nterror(req, &status)) {
418 DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
419 (int)state->nread, state->is_data_outstanding?"":"no "));
421 *nread = state->nread;
422 *is_data_outstanding = state->is_data_outstanding;