8a26afb4af83e576ab6a7812b6871959addc8a27
[nivanova/samba-autobuild/.git] / source3 / rpc_server / srv_pipe_hnd.c
1 /*
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
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include "includes.h"
23 #include "fake_file.h"
24 #include "rpc_dce.h"
25 #include "ntdomain.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"
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_RPC_SRV
37
38 /****************************************************************************
39  Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
40 ****************************************************************************/
41
42 static ssize_t fill_rpc_header(struct pipes_struct *p, const char *data, size_t data_to_copy)
43 {
44         size_t len_needed_to_complete_hdr =
45                 MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu.length);
46
47         DEBUG(10, ("fill_rpc_header: data_to_copy = %u, "
48                    "len_needed_to_complete_hdr = %u, "
49                    "receive_len = %u\n",
50                    (unsigned int)data_to_copy,
51                    (unsigned int)len_needed_to_complete_hdr,
52                    (unsigned int)p->in_data.pdu.length ));
53
54         if (p->in_data.pdu.data == NULL) {
55                 p->in_data.pdu.data = talloc_array(p, uint8_t, RPC_HEADER_LEN);
56         }
57         if (p->in_data.pdu.data == NULL) {
58                 DEBUG(0, ("talloc failed\n"));
59                 return -1;
60         }
61
62         memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
63                 data, len_needed_to_complete_hdr);
64         p->in_data.pdu.length += len_needed_to_complete_hdr;
65
66         return (ssize_t)len_needed_to_complete_hdr;
67 }
68
69 static bool get_pdu_size(struct pipes_struct *p)
70 {
71         uint16_t frag_len;
72         /* the fill_rpc_header() call insures we copy only
73          * RPC_HEADER_LEN bytes. If this doesn't match then
74          * somethign is very wrong and we can only abort */
75         if (p->in_data.pdu.length != RPC_HEADER_LEN) {
76                 DEBUG(0, ("Unexpected RPC Header size! "
77                           "got %d, expected %d)\n",
78                           (int)p->in_data.pdu.length,
79                           RPC_HEADER_LEN));
80                 set_incoming_fault(p);
81                 return false;
82         }
83
84         frag_len = dcerpc_get_frag_length(&p->in_data.pdu);
85
86         /* verify it is a reasonable value */
87         if ((frag_len < RPC_HEADER_LEN) ||
88             (frag_len > RPC_MAX_PDU_FRAG_LEN)) {
89                 DEBUG(0, ("Unexpected RPC Fragment size! (%d)\n",
90                           frag_len));
91                 set_incoming_fault(p);
92                 return false;
93         }
94
95         p->in_data.pdu_needed_len = frag_len - RPC_HEADER_LEN;
96
97         /* allocate the space needed to fill the pdu */
98         p->in_data.pdu.data = talloc_realloc(p, p->in_data.pdu.data,
99                                                 uint8_t, frag_len);
100         if (p->in_data.pdu.data == NULL) {
101                 DEBUG(0, ("talloc_realloc failed\n"));
102                 set_incoming_fault(p);
103                 return false;
104         }
105
106         return true;
107 }
108
109 /****************************************************************************
110   Call this to free any talloc'ed memory. Do this after processing
111   a complete incoming and outgoing request (multiple incoming/outgoing
112   PDU's).
113 ****************************************************************************/
114
115 static void free_pipe_context(struct pipes_struct *p)
116 {
117         data_blob_free(&p->out_data.frag);
118         data_blob_free(&p->out_data.rdata);
119         data_blob_free(&p->in_data.data);
120
121         DEBUG(3, ("free_pipe_context: "
122                 "destroying talloc pool of size %lu\n",
123                 (unsigned long)talloc_total_size(p->mem_ctx)));
124         talloc_free_children(p->mem_ctx);
125 }
126
127 /****************************************************************************
128  Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
129 ****************************************************************************/
130
131 ssize_t process_incoming_data(struct pipes_struct *p, const char *data, size_t n)
132 {
133         size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN
134                                         - p->in_data.pdu.length);
135
136         DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, "
137                    "pdu_needed_len = %u, incoming data = %u\n",
138                    (unsigned int)p->in_data.pdu.length,
139                    (unsigned int)p->in_data.pdu_needed_len,
140                    (unsigned int)n ));
141
142         if(data_to_copy == 0) {
143                 /*
144                  * This is an error - data is being received and there is no
145                  * space in the PDU. Free the received data and go into the
146                  * fault state.
147                  */
148                 DEBUG(0, ("process_incoming_data: "
149                           "No space in incoming pdu buffer. "
150                           "Current size = %u incoming data size = %u\n",
151                           (unsigned int)p->in_data.pdu.length,
152                           (unsigned int)n));
153                 set_incoming_fault(p);
154                 return -1;
155         }
156
157         /*
158          * If we have no data already, wait until we get at least
159          * a RPC_HEADER_LEN * number of bytes before we can do anything.
160          */
161
162         if ((p->in_data.pdu_needed_len == 0) &&
163             (p->in_data.pdu.length < RPC_HEADER_LEN)) {
164                 /*
165                  * Always return here. If we have more data then the RPC_HEADER
166                  * will be processed the next time around the loop.
167                  */
168                 return fill_rpc_header(p, data, data_to_copy);
169         }
170
171         /*
172          * At this point we know we have at least an RPC_HEADER_LEN amount of
173          * data stored in p->in_data.pdu.
174          */
175
176         /*
177          * If pdu_needed_len is zero this is a new pdu.
178          * Check how much more data we need, then loop again.
179          */
180         if (p->in_data.pdu_needed_len == 0) {
181
182                 bool ok = get_pdu_size(p);
183                 if (!ok) {
184                         return -1;
185                 }
186                 if (p->in_data.pdu_needed_len > 0) {
187                         return 0;
188                 }
189
190                 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU
191                  * that consists of an RPC_HEADER only. This is a
192                  * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or
193                  * DCERPC_PKT_ORPHANED pdu type.
194                  * Deal with this in process_complete_pdu(). */
195         }
196
197         /*
198          * Ok - at this point we have a valid RPC_HEADER.
199          * Keep reading until we have a full pdu.
200          */
201
202         data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
203
204         /*
205          * Copy as much of the data as we need into the p->in_data.pdu buffer.
206          * pdu_needed_len becomes zero when we have a complete pdu.
207          */
208
209         memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
210                 data, data_to_copy);
211         p->in_data.pdu.length += data_to_copy;
212         p->in_data.pdu_needed_len -= data_to_copy;
213
214         /*
215          * Do we have a complete PDU ?
216          * (return the number of bytes handled in the call)
217          */
218
219         if(p->in_data.pdu_needed_len == 0) {
220                 process_complete_pdu(p);
221                 return data_to_copy;
222         }
223
224         DEBUG(10, ("process_incoming_data: not a complete PDU yet. "
225                    "pdu.length = %u, pdu_needed_len = %u\n",
226                    (unsigned int)p->in_data.pdu.length,
227                    (unsigned int)p->in_data.pdu_needed_len));
228
229         return (ssize_t)data_to_copy;
230 }
231
232 /****************************************************************************
233  Accepts incoming data on an internal rpc pipe.
234 ****************************************************************************/
235
236 static ssize_t write_to_internal_pipe(struct pipes_struct *p, const char *data, size_t n)
237 {
238         size_t data_left = n;
239
240         while(data_left) {
241                 ssize_t data_used;
242
243                 DEBUG(10, ("write_to_pipe: data_left = %u\n",
244                           (unsigned int)data_left));
245
246                 data_used = process_incoming_data(p, data, data_left);
247
248                 DEBUG(10, ("write_to_pipe: data_used = %d\n",
249                            (int)data_used));
250
251                 if(data_used < 0) {
252                         return -1;
253                 }
254
255                 data_left -= data_used;
256                 data += data_used;
257         }
258
259         return n;
260 }
261
262 /****************************************************************************
263  Replies to a request to read data from a pipe.
264
265  Headers are interspersed with the data at PDU intervals. By the time
266  this function is called, the start of the data could possibly have been
267  read by an SMBtrans (file_offset != 0).
268
269  Calling create_rpc_reply() here is a hack. The data should already
270  have been prepared into arrays of headers + data stream sections.
271 ****************************************************************************/
272
273 static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data,
274                                        size_t n, bool *is_data_outstanding)
275 {
276         uint32 pdu_remaining = 0;
277         ssize_t data_returned = 0;
278
279         if (!p) {
280                 DEBUG(0,("read_from_pipe: pipe not open\n"));
281                 return -1;
282         }
283
284         DEBUG(6,(" name: %s len: %u\n",
285                  ndr_interface_name(&p->contexts->syntax.uuid,
286                                     p->contexts->syntax.if_version),
287                  (unsigned int)n));
288
289         /*
290          * We cannot return more than one PDU length per
291          * read request.
292          */
293
294         /*
295          * This condition should result in the connection being closed.
296          * Netapp filers seem to set it to 0xffff which results in domain
297          * authentications failing.  Just ignore it so things work.
298          */
299
300         if(n > RPC_MAX_PDU_FRAG_LEN) {
301                 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
302                          "pipe %s. We can only service %d sized reads.\n",
303                          (unsigned int)n,
304                          ndr_interface_name(&p->contexts->syntax.uuid,
305                                             p->contexts->syntax.if_version),
306                          RPC_MAX_PDU_FRAG_LEN ));
307                 n = RPC_MAX_PDU_FRAG_LEN;
308         }
309
310         /*
311          * Determine if there is still data to send in the
312          * pipe PDU buffer. Always send this first. Never
313          * send more than is left in the current PDU. The
314          * client should send a new read request for a new
315          * PDU.
316          */
317
318         pdu_remaining = p->out_data.frag.length
319                 - p->out_data.current_pdu_sent;
320
321         if (pdu_remaining > 0) {
322                 data_returned = (ssize_t)MIN(n, pdu_remaining);
323
324                 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
325                           "current_pdu_sent = %u returning %d bytes.\n",
326                           ndr_interface_name(&p->contexts->syntax.uuid,
327                                              p->contexts->syntax.if_version),
328                           (unsigned int)p->out_data.frag.length,
329                           (unsigned int)p->out_data.current_pdu_sent,
330                           (int)data_returned));
331
332                 memcpy(data,
333                        p->out_data.frag.data
334                        + p->out_data.current_pdu_sent,
335                        data_returned);
336
337                 p->out_data.current_pdu_sent += (uint32)data_returned;
338                 goto out;
339         }
340
341         /*
342          * At this point p->current_pdu_len == p->current_pdu_sent (which
343          * may of course be zero if this is the first return fragment.
344          */
345
346         DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
347                   "= %u, p->out_data.rdata.length = %u.\n",
348                   ndr_interface_name(&p->contexts->syntax.uuid,
349                                      p->contexts->syntax.if_version),
350                   (int)p->fault_state,
351                   (unsigned int)p->out_data.data_sent_length,
352                   (unsigned int)p->out_data.rdata.length));
353
354         if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
355                 /*
356                  * We have sent all possible data, return 0.
357                  */
358                 data_returned = 0;
359                 goto out;
360         }
361
362         /*
363          * We need to create a new PDU from the data left in p->rdata.
364          * Create the header/data/footers. This also sets up the fields
365          * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
366          * and stores the outgoing PDU in p->current_pdu.
367          */
368
369         if(!create_next_pdu(p)) {
370                 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
371                          ndr_interface_name(&p->contexts->syntax.uuid,
372                                             p->contexts->syntax.if_version)));
373                 return -1;
374         }
375
376         data_returned = MIN(n, p->out_data.frag.length);
377
378         memcpy(data, p->out_data.frag.data, (size_t)data_returned);
379         p->out_data.current_pdu_sent += (uint32)data_returned;
380
381   out:
382         (*is_data_outstanding) = p->out_data.frag.length > n;
383
384         if (p->out_data.current_pdu_sent == p->out_data.frag.length) {
385                 /* We've returned everything in the out_data.frag
386                  * so we're done with this pdu. Free it and reset
387                  * current_pdu_sent. */
388                 p->out_data.current_pdu_sent = 0;
389                 data_blob_free(&p->out_data.frag);
390
391                 if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
392                         /*
393                          * We're completely finished with both outgoing and
394                          * incoming data streams. It's safe to free all
395                          * temporary data from this request.
396                          */
397                         free_pipe_context(p);
398                 }
399         }
400
401         return data_returned;
402 }
403
404 bool fsp_is_np(struct files_struct *fsp)
405 {
406         enum FAKE_FILE_TYPE type;
407
408         if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
409                 return false;
410         }
411
412         type = fsp->fake_file_handle->type;
413
414         return ((type == FAKE_FILE_TYPE_NAMED_PIPE)
415                 || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY));
416 }
417
418 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
419                  const struct tsocket_address *local_address,
420                  const struct tsocket_address *remote_address,
421                  struct auth_session_info *session_info,
422                  struct tevent_context *ev_ctx,
423                  struct messaging_context *msg_ctx,
424                  struct fake_file_handle **phandle)
425 {
426         enum rpc_service_mode_e pipe_mode;
427         const char **proxy_list;
428         struct fake_file_handle *handle;
429         struct ndr_syntax_id syntax;
430         struct npa_state *npa = NULL;
431         NTSTATUS status;
432         bool ok;
433
434         proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
435
436         handle = talloc(mem_ctx, struct fake_file_handle);
437         if (handle == NULL) {
438                 return NT_STATUS_NO_MEMORY;
439         }
440
441         /* Check what is the server type for this pipe.
442            Defaults to "embedded" */
443         pipe_mode = rpc_service_mode(name);
444
445         /* Still support the old method for defining external servers */
446         if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
447                 pipe_mode = RPC_SERVICE_MODE_EXTERNAL;
448         }
449
450         switch (pipe_mode) {
451         case RPC_SERVICE_MODE_EXTERNAL:
452                 status = make_external_rpc_pipe(handle,
453                                                 name,
454                                                 local_address,
455                                                 remote_address,
456                                                 session_info,
457                                                 &npa);
458                 if (!NT_STATUS_IS_OK(status)) {
459                         talloc_free(handle);
460                         return status;
461                 }
462
463                 handle->private_data = (void *)npa;
464                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
465
466                 break;
467         case RPC_SERVICE_MODE_EMBEDDED:
468                 /* Check if we this daemon handles this pipe */
469                 ok = is_known_pipename(name, &syntax);
470                 if (!ok) {
471                         DEBUG(0, ("ERROR! '%s' is not a registred pipe!\n",
472                                   name));
473                         talloc_free(handle);
474                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
475                 }
476
477                 status = make_internal_rpc_pipe_socketpair(handle,
478                                                            ev_ctx,
479                                                            msg_ctx,
480                                                            name,
481                                                            &syntax,
482                                                            remote_address,
483                                                            session_info,
484                                                            &npa);
485                 if (!NT_STATUS_IS_OK(status)) {
486                         talloc_free(handle);
487                         return status;
488                 }
489
490                 handle->private_data = (void *)npa;
491                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
492
493                 break;
494         case RPC_SERVICE_MODE_DISABLED:
495                 talloc_free(handle);
496                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
497         }
498
499         *phandle = handle;
500
501         return NT_STATUS_OK;
502 }
503
504 bool np_read_in_progress(struct fake_file_handle *handle)
505 {
506         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
507                 return false;
508         }
509
510         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
511                 struct npa_state *p =
512                         talloc_get_type_abort(handle->private_data,
513                                               struct npa_state);
514                 size_t read_count;
515
516                 read_count = tevent_queue_length(p->read_queue);
517                 if (read_count > 0) {
518                         return true;
519                 }
520
521                 return false;
522         }
523
524         return false;
525 }
526
527 struct np_write_state {
528         struct tevent_context *ev;
529         struct npa_state *p;
530         struct iovec iov;
531         ssize_t nwritten;
532 };
533
534 static void np_write_done(struct tevent_req *subreq);
535
536 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
537                                  struct fake_file_handle *handle,
538                                  const uint8_t *data, size_t len)
539 {
540         struct tevent_req *req;
541         struct np_write_state *state;
542         NTSTATUS status;
543
544         DEBUG(6, ("np_write_send: len: %d\n", (int)len));
545         dump_data(50, data, len);
546
547         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
548         if (req == NULL) {
549                 return NULL;
550         }
551
552         if (len == 0) {
553                 state->nwritten = 0;
554                 status = NT_STATUS_OK;
555                 goto post_status;
556         }
557
558         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
559                 struct npa_state *npa =
560                         talloc_get_type_abort(handle->private_data,
561                                               struct npa_state);
562                 struct pipes_struct *p =
563                         talloc_get_type_abort(npa->private_data,
564                                               struct pipes_struct);
565
566                 state->nwritten = write_to_internal_pipe(p, (const char *)data, len);
567
568                 status = (state->nwritten >= 0)
569                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
570                 goto post_status;
571         }
572
573         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
574                 struct npa_state *p = talloc_get_type_abort(
575                         handle->private_data, struct npa_state);
576                 struct tevent_req *subreq;
577
578                 state->ev = ev;
579                 state->p = p;
580                 state->iov.iov_base = discard_const_p(void, data);
581                 state->iov.iov_len = len;
582
583                 subreq = tstream_writev_queue_send(state, ev,
584                                                    p->stream,
585                                                    p->write_queue,
586                                                    &state->iov, 1);
587                 if (subreq == NULL) {
588                         goto fail;
589                 }
590                 tevent_req_set_callback(subreq, np_write_done, req);
591                 return req;
592         }
593
594         status = NT_STATUS_INVALID_HANDLE;
595  post_status:
596         if (NT_STATUS_IS_OK(status)) {
597                 tevent_req_done(req);
598         } else {
599                 tevent_req_nterror(req, status);
600         }
601         return tevent_req_post(req, ev);
602  fail:
603         TALLOC_FREE(req);
604         return NULL;
605 }
606
607 static void np_write_done(struct tevent_req *subreq)
608 {
609         struct tevent_req *req = tevent_req_callback_data(
610                 subreq, struct tevent_req);
611         struct np_write_state *state = tevent_req_data(
612                 req, struct np_write_state);
613         ssize_t received;
614         int err;
615
616         received = tstream_writev_queue_recv(subreq, &err);
617         if (received < 0) {
618                 tevent_req_nterror(req, map_nt_error_from_unix(err));
619                 return;
620         }
621         state->nwritten = received;
622         tevent_req_done(req);
623 }
624
625 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
626 {
627         struct np_write_state *state = tevent_req_data(
628                 req, struct np_write_state);
629         NTSTATUS status;
630
631         if (tevent_req_is_nterror(req, &status)) {
632                 return status;
633         }
634         *pnwritten = state->nwritten;
635         return NT_STATUS_OK;
636 }
637
638 struct np_ipc_readv_next_vector_state {
639         uint8_t *buf;
640         size_t len;
641         off_t ofs;
642         size_t remaining;
643 };
644
645 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
646                                           uint8_t *buf, size_t len)
647 {
648         ZERO_STRUCTP(s);
649
650         s->buf = buf;
651         s->len = MIN(len, UINT16_MAX);
652 }
653
654 static int np_ipc_readv_next_vector(struct tstream_context *stream,
655                                     void *private_data,
656                                     TALLOC_CTX *mem_ctx,
657                                     struct iovec **_vector,
658                                     size_t *count)
659 {
660         struct np_ipc_readv_next_vector_state *state =
661                 (struct np_ipc_readv_next_vector_state *)private_data;
662         struct iovec *vector;
663         ssize_t pending;
664         size_t wanted;
665
666         if (state->ofs == state->len) {
667                 *_vector = NULL;
668                 *count = 0;
669                 return 0;
670         }
671
672         pending = tstream_pending_bytes(stream);
673         if (pending == -1) {
674                 return -1;
675         }
676
677         if (pending == 0 && state->ofs != 0) {
678                 /* return a short read */
679                 *_vector = NULL;
680                 *count = 0;
681                 return 0;
682         }
683
684         if (pending == 0) {
685                 /* we want at least one byte and recheck again */
686                 wanted = 1;
687         } else {
688                 size_t missing = state->len - state->ofs;
689                 if (pending > missing) {
690                         /* there's more available */
691                         state->remaining = pending - missing;
692                         wanted = missing;
693                 } else {
694                         /* read what we can get and recheck in the next cycle */
695                         wanted = pending;
696                 }
697         }
698
699         vector = talloc_array(mem_ctx, struct iovec, 1);
700         if (!vector) {
701                 return -1;
702         }
703
704         vector[0].iov_base = state->buf + state->ofs;
705         vector[0].iov_len = wanted;
706
707         state->ofs += wanted;
708
709         *_vector = vector;
710         *count = 1;
711         return 0;
712 }
713
714 struct np_read_state {
715         struct npa_state *p;
716         struct np_ipc_readv_next_vector_state next_vector;
717
718         ssize_t nread;
719         bool is_data_outstanding;
720 };
721
722 static void np_read_done(struct tevent_req *subreq);
723
724 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
725                                 struct fake_file_handle *handle,
726                                 uint8_t *data, size_t len)
727 {
728         struct tevent_req *req;
729         struct np_read_state *state;
730         NTSTATUS status;
731
732         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
733         if (req == NULL) {
734                 return NULL;
735         }
736
737         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
738                 struct npa_state *npa =
739                         talloc_get_type_abort(handle->private_data,
740                                               struct npa_state);
741                 struct pipes_struct *p =
742                         talloc_get_type_abort(npa->private_data,
743                                               struct pipes_struct);
744
745                 state->nread = read_from_internal_pipe(
746                         p, (char *)data, len, &state->is_data_outstanding);
747
748                 status = (state->nread >= 0)
749                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
750                 goto post_status;
751         }
752
753         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
754                 struct npa_state *p = talloc_get_type_abort(
755                         handle->private_data, struct npa_state);
756                 struct tevent_req *subreq;
757
758                 np_ipc_readv_next_vector_init(&state->next_vector,
759                                               data, len);
760
761                 subreq = tstream_readv_pdu_queue_send(state,
762                                                       ev,
763                                                       p->stream,
764                                                       p->read_queue,
765                                                       np_ipc_readv_next_vector,
766                                                       &state->next_vector);
767                 if (subreq == NULL) {
768                         status = NT_STATUS_NO_MEMORY;
769                         goto post_status;
770                 }
771                 tevent_req_set_callback(subreq, np_read_done, req);
772                 return req;
773         }
774
775         status = NT_STATUS_INVALID_HANDLE;
776  post_status:
777         if (NT_STATUS_IS_OK(status)) {
778                 tevent_req_done(req);
779         } else {
780                 tevent_req_nterror(req, status);
781         }
782         return tevent_req_post(req, ev);
783 }
784
785 static void np_read_done(struct tevent_req *subreq)
786 {
787         struct tevent_req *req = tevent_req_callback_data(
788                 subreq, struct tevent_req);
789         struct np_read_state *state = tevent_req_data(
790                 req, struct np_read_state);
791         ssize_t ret;
792         int err;
793
794         ret = tstream_readv_pdu_queue_recv(subreq, &err);
795         TALLOC_FREE(subreq);
796         if (ret == -1) {
797                 tevent_req_nterror(req, map_nt_error_from_unix(err));
798                 return;
799         }
800
801         state->nread = ret;
802         state->is_data_outstanding = (state->next_vector.remaining > 0);
803
804         tevent_req_done(req);
805         return;
806 }
807
808 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
809                       bool *is_data_outstanding)
810 {
811         struct np_read_state *state = tevent_req_data(
812                 req, struct np_read_state);
813         NTSTATUS status;
814
815         if (tevent_req_is_nterror(req, &status)) {
816                 return status;
817         }
818
819         DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
820                    (int)state->nread, state->is_data_outstanding?"":"no "));
821
822         *nread = state->nread;
823         *is_data_outstanding = state->is_data_outstanding;
824         return NT_STATUS_OK;
825 }