s3:rpc_server: Split dcerpc_ncacn_accept to deal with tstream_npa
[samba.git] / source3 / rpc_server / rpc_server.c
1 /*
2    Unix SMB/Netbios implementation.
3    Generic infrstructure for RPC Daemons
4    Copyright (C) Simo Sorce 2010
5    Copyright (C) Andrew Bartlett 2011
6    Copyright (C) Andreas Schneider 2011
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 "rpc_server/rpc_pipes.h"
24 #include "rpc_server/rpc_server.h"
25 #include "rpc_server/rpc_config.h"
26 #include "rpc_dce.h"
27 #include "librpc/gen_ndr/netlogon.h"
28 #include "librpc/gen_ndr/auth.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "libcli/named_pipe_auth/npa_tstream.h"
31 #include "../auth/auth_sam_reply.h"
32 #include "auth.h"
33 #include "rpc_server/rpc_ncacn_np.h"
34 #include "rpc_server/srv_pipe_hnd.h"
35 #include "rpc_server/srv_pipe.h"
36
37 /* Creates a pipes_struct and initializes it with the information
38  * sent from the client */
39 int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
40                              struct messaging_context *msg_ctx,
41                              const char *pipe_name,
42                              enum dcerpc_transport_t transport,
43                              const struct tsocket_address *remote_address,
44                              const struct tsocket_address *local_address,
45                              struct auth_session_info **psession_info,
46                              struct pipes_struct **_p,
47                              int *perrno)
48 {
49         struct auth_session_info *session_info = *psession_info;
50         struct pipes_struct *p;
51         int ret;
52
53         ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
54                                      transport, RPC_LITTLE_ENDIAN,
55                                      remote_address, local_address, &p);
56         if (ret) {
57                 *perrno = ret;
58                 return -1;
59         }
60
61         if ((session_info->unix_token == NULL) ||
62             (session_info->unix_info == NULL) ||
63             (session_info->security_token == NULL)) {
64                 DBG_ERR("Supplied session_info was incomplete!\n");
65                 TALLOC_FREE(p);
66                 *perrno = EINVAL;
67                 return -1;
68         }
69
70         /* Don't call create_local_token(), we already have the full details here */
71         p->session_info = talloc_move(p, psession_info);
72
73         *_p = p;
74         return 0;
75 }
76
77 /* Start listening on the appropriate unix socket and setup all is needed to
78  * dispatch requests to the pipes rpc implementation */
79
80 struct dcerpc_ncacn_listen_state {
81         struct ndr_syntax_id syntax_id;
82
83         int fd;
84         union {
85                 char *name;
86                 uint16_t port;
87         } ep;
88
89         struct tevent_context *ev_ctx;
90         struct messaging_context *msg_ctx;
91         dcerpc_ncacn_disconnect_fn disconnect_fn;
92         dcerpc_ncacn_termination_fn termination_fn;
93         void *termination_data;
94 };
95
96 static void dcesrv_ncacn_np_listener(struct tevent_context *ev,
97                                      struct tevent_fd *fde,
98                                      uint16_t flags,
99                                      void *private_data);
100
101 NTSTATUS dcesrv_create_ncacn_np_socket(const char *pipe_name, int *out_fd)
102 {
103         char *np_dir = NULL;
104         int fd = -1;
105         NTSTATUS status;
106
107         /*
108          * As lp_ncalrpc_dir() should have 0755, but
109          * lp_ncalrpc_dir()/np should have 0700, we need to
110          * create lp_ncalrpc_dir() first.
111          */
112         if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
113                 status = map_nt_error_from_unix_common(errno);
114                 DBG_ERR("Failed to create pipe directory %s - %s\n",
115                         lp_ncalrpc_dir(), strerror(errno));
116                 goto out;
117         }
118
119         np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
120         if (!np_dir) {
121                 status = NT_STATUS_NO_MEMORY;
122                 DBG_ERR("Out of memory\n");
123                 goto out;
124         }
125
126         if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
127                 status = map_nt_error_from_unix_common(errno);
128                 DBG_ERR("Failed to create pipe directory %s - %s\n",
129                         np_dir, strerror(errno));
130                 goto out;
131         }
132
133         fd = create_pipe_sock(np_dir, pipe_name, 0700);
134         if (fd == -1) {
135                 status = map_nt_error_from_unix_common(errno);
136                 DBG_ERR("Failed to create ncacn_np socket! '%s/%s': %s\n",
137                         np_dir, pipe_name, strerror(errno));
138                 goto out;
139         }
140
141         DBG_DEBUG("Opened pipe socket fd %d for %s\n", fd, pipe_name);
142
143         *out_fd = fd;
144
145         status = NT_STATUS_OK;
146
147 out:
148         talloc_free(np_dir);
149         return status;
150 }
151
152 NTSTATUS dcesrv_setup_ncacn_np_socket(const char *pipe_name,
153                                       struct tevent_context *ev_ctx,
154                                       struct messaging_context *msg_ctx)
155 {
156         struct dcerpc_ncacn_listen_state *state;
157         struct tevent_fd *fde;
158         int rc;
159         NTSTATUS status;
160
161         state = talloc_zero(ev_ctx, struct dcerpc_ncacn_listen_state);
162         if (state == NULL) {
163                 DBG_ERR("Out of memory\n");
164                 return NT_STATUS_NO_MEMORY;
165         }
166         state->fd = -1;
167         state->ep.name = talloc_strdup(state, pipe_name);
168         if (state->ep.name == NULL) {
169                 DBG_ERR("Out of memory\n");
170                 status = NT_STATUS_NO_MEMORY;
171                 goto out;
172         }
173         status = dcesrv_create_ncacn_np_socket(pipe_name, &state->fd);
174         if (!NT_STATUS_IS_OK(status)) {
175                 goto out;
176         }
177
178         rc = listen(state->fd, 5);
179         if (rc < 0) {
180                 status = map_nt_error_from_unix_common(errno);
181                 DBG_ERR("Failed to listen on ncacn_np socket %s: %s\n",
182                         pipe_name, strerror(errno));
183                 goto out;
184         }
185
186         state->ev_ctx = ev_ctx;
187         state->msg_ctx = msg_ctx;
188
189         DBG_DEBUG("Opened pipe socket fd %d for %s\n",
190                   state->fd, pipe_name);
191
192         errno = 0;
193         fde = tevent_add_fd(ev_ctx,
194                             state, state->fd, TEVENT_FD_READ,
195                             dcesrv_ncacn_np_listener, state);
196         if (fde == NULL) {
197                 if (errno == 0) {
198                         errno = ENOMEM;
199                 }
200                 status = map_nt_error_from_unix_common(errno);
201                 DBG_ERR("Failed to add event handler for ncacn_np: %s\n",
202                         strerror(errno));
203                 goto out;
204         }
205
206         tevent_fd_set_auto_close(fde);
207         return NT_STATUS_OK;
208
209 out:
210         if (state->fd != -1) {
211                 close(state->fd);
212         }
213         TALLOC_FREE(state);
214         return status;
215 }
216
217 static void dcesrv_ncacn_np_listener(struct tevent_context *ev,
218                                      struct tevent_fd *fde,
219                                      uint16_t flags,
220                                      void *private_data)
221 {
222         struct dcerpc_ncacn_listen_state *state =
223                         talloc_get_type_abort(private_data,
224                                               struct dcerpc_ncacn_listen_state);
225         struct samba_sockaddr addr = {
226                 .sa_socklen = sizeof(struct sockaddr_un),
227         };
228         int sd = -1;
229
230         /* TODO: should we have a limit to the number of clients ? */
231
232         sd = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
233
234         if (sd == -1) {
235                 if (errno != EINTR) {
236                         DEBUG(6, ("Failed to get a valid socket [%s]\n",
237                                   strerror(errno)));
238                 }
239                 return;
240         }
241         smb_set_close_on_exec(sd);
242
243         DBG_DEBUG("Accepted ncacn_np socket %s (fd: %d)\n",
244                    addr.u.un.sun_path, sd);
245
246         named_pipe_accept_function(state->ev_ctx,
247                                    state->msg_ctx,
248                                    state->ep.name,
249                                    sd, NULL, 0);
250 }
251
252
253 /* This is the core of the rpc server.
254  * Accepts connections from clients and process requests using the appropriate
255  * dispatcher table. */
256
257 static int named_pipe_destructor(struct named_pipe_client *npc)
258 {
259         if (npc->term_fn) {
260                 npc->term_fn(npc->private_data);
261         }
262         return 0;
263 }
264
265 struct named_pipe_client *named_pipe_client_init(TALLOC_CTX *mem_ctx,
266                                                  struct tevent_context *ev_ctx,
267                                                  struct messaging_context *msg_ctx,
268                                                  const char *pipe_name,
269                                                  named_pipe_termination_fn term_fn,
270                                                  uint16_t file_type,
271                                                  uint16_t device_state,
272                                                  uint64_t allocation_size,
273                                                  void *private_data)
274 {
275         struct named_pipe_client *npc;
276
277         npc = talloc_zero(mem_ctx, struct named_pipe_client);
278         if (npc == NULL) {
279                 DEBUG(0, ("Out of memory!\n"));
280                 return NULL;
281         }
282         talloc_set_destructor(npc, named_pipe_destructor);
283
284         npc->pipe_name = talloc_strdup(npc, pipe_name);
285         if (npc->pipe_name == NULL) {
286                 DEBUG(0, ("Out of memory!\n"));
287                 talloc_free(npc);
288                 return NULL;
289         }
290
291         npc->ev = ev_ctx;
292         npc->msg_ctx = msg_ctx;
293         npc->term_fn = term_fn;
294         npc->private_data = private_data;
295
296         npc->file_type = file_type;
297         npc->device_state = device_state;
298         npc->allocation_size = allocation_size;
299
300         return npc;
301 }
302
303 static void named_pipe_accept_done(struct tevent_req *subreq);
304
305 void named_pipe_accept_function(struct tevent_context *ev_ctx,
306                                 struct messaging_context *msg_ctx,
307                                 const char *pipe_name, int fd,
308                                 named_pipe_termination_fn term_fn,
309                                 void *private_data)
310 {
311         struct named_pipe_client *npc;
312         struct tstream_context *plain;
313         struct tevent_req *subreq;
314         int ret;
315
316         npc = named_pipe_client_init(
317                 ev_ctx,
318                 ev_ctx,
319                 msg_ctx,
320                 pipe_name,
321                 term_fn,
322                 FILE_TYPE_MESSAGE_MODE_PIPE, /* file_type */
323                 0xff | 0x0400 | 0x0100,      /* device_state */
324                 4096,                        /* allocation_size */
325                 private_data);
326         if (npc == NULL) {
327                 DEBUG(0, ("Out of memory!\n"));
328                 close(fd);
329                 return;
330         }
331
332         /* make sure socket is in NON blocking state */
333         ret = set_blocking(fd, false);
334         if (ret != 0) {
335                 DEBUG(2, ("Failed to make socket non-blocking\n"));
336                 TALLOC_FREE(npc);
337                 close(fd);
338                 return;
339         }
340
341         ret = tstream_bsd_existing_socket(npc, fd, &plain);
342         if (ret != 0) {
343                 DEBUG(2, ("Failed to create tstream socket\n"));
344                 TALLOC_FREE(npc);
345                 close(fd);
346                 return;
347         }
348
349         subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
350                                                   npc->file_type,
351                                                   npc->device_state,
352                                                   npc->allocation_size);
353         if (!subreq) {
354                 DEBUG(2, ("Failed to start async accept procedure\n"));
355                 TALLOC_FREE(npc);
356                 close(fd);
357                 return;
358         }
359         tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
360 }
361
362 static void named_pipe_packet_done(struct tevent_req *subreq);
363
364 static void named_pipe_accept_done(struct tevent_req *subreq)
365 {
366         struct auth_session_info_transport *session_info_transport;
367         struct named_pipe_client *npc =
368                 tevent_req_callback_data(subreq, struct named_pipe_client);
369         int error;
370         int ret;
371
372         ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
373                                                 &npc->tstream,
374                                                 &npc->remote_client_addr,
375                                                 &npc->remote_client_name,
376                                                 &npc->local_server_addr,
377                                                 &npc->local_server_name,
378                                                 &session_info_transport);
379
380         TALLOC_FREE(subreq);
381         if (ret != 0) {
382                 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
383                           strerror(error)));
384                 TALLOC_FREE(npc);
385                 return;
386         }
387
388         npc->session_info = talloc_move(
389                 npc, &session_info_transport->session_info);
390
391         ret = make_server_pipes_struct(npc,
392                                        npc->msg_ctx,
393                                        npc->pipe_name, NCACN_NP,
394                                        npc->remote_client_addr,
395                                        npc->local_server_addr,
396                                        &npc->session_info,
397                                        &npc->p, &error);
398         if (ret != 0) {
399                 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
400                           strerror(error)));
401                 goto fail;
402         }
403
404         npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
405         if (!npc->write_queue) {
406                 DEBUG(2, ("Failed to set up write queue!\n"));
407                 goto fail;
408         }
409
410         /* And now start receiving and processing packets */
411         subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
412         if (!subreq) {
413                 DEBUG(2, ("Failed to start receiving packets\n"));
414                 goto fail;
415         }
416         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
417         return;
418
419 fail:
420         DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
421                   npc->remote_client_name));
422         /* terminate client connection */
423         talloc_free(npc);
424         return;
425 }
426
427 void named_pipe_packet_process(struct tevent_req *subreq)
428 {
429         struct named_pipe_client *npc =
430                 tevent_req_callback_data(subreq, struct named_pipe_client);
431         struct _output_data *out = &npc->p->out_data;
432         DATA_BLOB recv_buffer = data_blob_null;
433         struct ncacn_packet *pkt;
434         NTSTATUS status;
435         uint32_t to_send;
436         size_t i;
437         bool ok;
438
439         status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer);
440         TALLOC_FREE(subreq);
441         if (!NT_STATUS_IS_OK(status)) {
442                 goto fail;
443         }
444
445         /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
446         npc->p->in_data.pdu_needed_len = 0;
447         npc->p->in_data.pdu = recv_buffer;
448         if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
449                 npc->p->endian = RPC_LITTLE_ENDIAN;
450         } else {
451                 npc->p->endian = RPC_BIG_ENDIAN;
452         }
453         DEBUG(10, ("PDU is in %s Endian format!\n",
454                    npc->p->endian ? "Big" : "Little"));
455         process_complete_pdu(npc->p, pkt);
456
457         /* reset pipe state and free PDU */
458         npc->p->in_data.pdu.length = 0;
459         talloc_free(recv_buffer.data);
460         talloc_free(pkt);
461
462         /* this is needed because of the way DCERPC Binds work in
463          * the RPC marshalling code */
464         to_send = out->frag.length - out->current_pdu_sent;
465         if (to_send > 0) {
466
467                 npc->iov = talloc_zero(npc, struct iovec);
468                 if (!npc->iov) {
469                         status = NT_STATUS_NO_MEMORY;
470                         goto fail;
471                 }
472                 npc->count = 1;
473
474                 npc->iov[0].iov_base = out->frag.data
475                                         + out->current_pdu_sent;
476                 npc->iov[0].iov_len = to_send;
477
478                 out->current_pdu_sent += to_send;
479         }
480
481         /* this condition is false for bind packets, or when we haven't
482          * yet got a full request, and need to wait for more data from
483          * the client */
484         while (out->data_sent_length < out->rdata.length) {
485
486                 ok = create_next_pdu(npc->p);
487                 if (!ok) {
488                         DEBUG(3, ("Failed to create next PDU!\n"));
489                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
490                         goto fail;
491                 }
492
493                 npc->iov = talloc_realloc(npc, npc->iov,
494                                             struct iovec, npc->count + 1);
495                 if (!npc->iov) {
496                         status = NT_STATUS_NO_MEMORY;
497                         goto fail;
498                 }
499
500                 npc->iov[npc->count].iov_base = out->frag.data;
501                 npc->iov[npc->count].iov_len = out->frag.length;
502
503                 npc->count++;
504         }
505
506         /* we still don't have a complete request, go back and wait for more
507          * data */
508         if (npc->count == 0) {
509                 /* Wait for the next packet */
510                 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
511                 if (!subreq) {
512                         DEBUG(2, ("Failed to start receiving packets\n"));
513                         status = NT_STATUS_NO_MEMORY;
514                         goto fail;
515                 }
516                 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
517                 return;
518         }
519
520         DBG_DEBUG("Sending %zu fragments in a total of %"PRIu32" bytes\n",
521                   npc->count,
522                   npc->p->out_data.data_sent_length);
523
524         for (i = 0; i < npc->count; i++) {
525                 DBG_DEBUG("Sending PDU number: %zu, PDU Length: %zu\n",
526                           i,
527                           npc->iov[i].iov_len);
528                 dump_data(11, (const uint8_t *)npc->iov[i].iov_base,
529                                 npc->iov[i].iov_len);
530
531                 subreq = tstream_writev_queue_send(npc,
532                                                    npc->ev,
533                                                    npc->tstream,
534                                                    npc->write_queue,
535                                                    (npc->iov + i),
536                                                    1);
537                 if (!subreq) {
538                         DEBUG(2, ("Failed to send packet\n"));
539                         status = NT_STATUS_NO_MEMORY;
540                         goto fail;
541                 }
542                 tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
543         }
544
545         return;
546
547 fail:
548         DEBUG(2, ("Fatal error(%s). "
549                   "Terminating client(%s) connection!\n",
550                   nt_errstr(status), npc->remote_client_name));
551         /* terminate client connection */
552         talloc_free(npc);
553         return;
554 }
555
556 static void named_pipe_packet_done(struct tevent_req *subreq)
557 {
558         struct named_pipe_client *npc =
559                 tevent_req_callback_data(subreq, struct named_pipe_client);
560         int sys_errno;
561         int ret;
562
563         ret = tstream_writev_queue_recv(subreq, &sys_errno);
564         TALLOC_FREE(subreq);
565         if (ret == -1) {
566                 DEBUG(2, ("Writev failed!\n"));
567                 goto fail;
568         }
569
570         if (tevent_queue_length(npc->write_queue) > 0) {
571                 return;
572         }
573
574         if (npc->p->fault_state != 0) {
575                 DEBUG(2, ("Disconnect after fault\n"));
576                 sys_errno = EINVAL;
577                 goto fail;
578         }
579
580         /* clear out any data that may have been left around */
581         npc->count = 0;
582         TALLOC_FREE(npc->iov);
583         data_blob_free(&npc->p->in_data.data);
584         data_blob_free(&npc->p->out_data.frag);
585         data_blob_free(&npc->p->out_data.rdata);
586
587         talloc_free_children(npc->p->mem_ctx);
588
589         /* Wait for the next packet */
590         subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
591         if (!subreq) {
592                 DEBUG(2, ("Failed to start receiving packets\n"));
593                 sys_errno = ENOMEM;
594                 goto fail;
595         }
596         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
597         return;
598
599 fail:
600         DEBUG(2, ("Fatal error(%s). "
601                   "Terminating client(%s) connection!\n",
602                   strerror(sys_errno), npc->remote_client_name));
603         /* terminate client connection */
604         talloc_free(npc);
605         return;
606 }
607
608 /********************************************************************
609  * Start listening on the tcp/ip socket
610  ********************************************************************/
611
612 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context *ev,
613                                          struct tevent_fd *fde,
614                                          uint16_t flags,
615                                          void *private_data);
616
617 NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss,
618                                            uint16_t *port,
619                                            int *out_fd)
620 {
621         int fd = -1;
622
623         if (*port == 0) {
624                 uint16_t i;
625
626                 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
627                         fd = open_socket_in(SOCK_STREAM,
628                                             i,
629                                             0,
630                                             ifss,
631                                             false);
632                         if (fd >= 0) {
633                                 *port = i;
634                                 break;
635                         }
636                 }
637         } else {
638                 fd = open_socket_in(SOCK_STREAM,
639                                     *port,
640                                     0,
641                                     ifss,
642                                     true);
643         }
644         if (fd == -1) {
645                 DBG_ERR("Failed to create socket on port %u!\n", *port);
646                 return NT_STATUS_UNSUCCESSFUL;
647         }
648
649         DBG_DEBUG("Opened ncacn_ip_tcp socket fd %d for port %u\n", fd, *port);
650
651         *out_fd = fd;
652
653         return NT_STATUS_OK;
654 }
655
656 NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
657                                           struct messaging_context *msg_ctx,
658                                           const struct sockaddr_storage *ifss,
659                                           uint16_t *port)
660 {
661         struct dcerpc_ncacn_listen_state *state;
662         struct tevent_fd *fde;
663         int rc;
664         NTSTATUS status;
665
666         state = talloc_zero(ev_ctx, struct dcerpc_ncacn_listen_state);
667         if (state == NULL) {
668                 DBG_ERR("Out of memory\n");
669                 return NT_STATUS_NO_MEMORY;
670         }
671
672         state->fd = -1;
673         state->ep.port = *port;
674         state->disconnect_fn = NULL;
675
676         status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &state->ep.port,
677                                                    &state->fd);
678         if (!NT_STATUS_IS_OK(status)) {
679                 goto out;
680         }
681
682         state->ev_ctx = ev_ctx;
683         state->msg_ctx = msg_ctx;
684
685         /* ready to listen */
686         set_socket_options(state->fd, "SO_KEEPALIVE");
687         set_socket_options(state->fd, lp_socket_options());
688
689         /* Set server socket to non-blocking for the accept. */
690         set_blocking(state->fd, false);
691
692         rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
693         if (rc == -1) {
694                 status = map_nt_error_from_unix_common(errno);
695                 DBG_ERR("Failed to listen on ncacn_ip_tcp socket: %s\n",
696                         strerror(errno));
697                 goto out;
698         }
699
700         DBG_DEBUG("Opened socket fd %d for port %u\n",
701                   state->fd, state->ep.port);
702
703         errno = 0;
704         fde = tevent_add_fd(state->ev_ctx,
705                             state,
706                             state->fd,
707                             TEVENT_FD_READ,
708                             dcesrv_ncacn_ip_tcp_listener,
709                             state);
710         if (fde == NULL) {
711                 if (errno == 0) {
712                         errno = ENOMEM;
713                 }
714                 status = map_nt_error_from_unix_common(errno);
715                 DBG_ERR("Failed to add event handler for ncacn_ip_tcp: %s\n",
716                         strerror(errno));
717                 goto out;
718         }
719
720         tevent_fd_set_auto_close(fde);
721
722         *port = state->ep.port;
723
724         return NT_STATUS_OK;
725
726 out:
727         if (state->fd != -1) {
728                 close(state->fd);
729         }
730         TALLOC_FREE(state);
731
732         return status;
733 }
734
735 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context *ev,
736                                          struct tevent_fd *fde,
737                                          uint16_t flags,
738                                          void *private_data)
739 {
740         struct dcerpc_ncacn_listen_state *state =
741                 talloc_get_type_abort(private_data,
742                                       struct dcerpc_ncacn_listen_state);
743         struct tsocket_address *cli_addr = NULL;
744         struct tsocket_address *srv_addr = NULL;
745         struct samba_sockaddr addr = {
746                 .sa_socklen = sizeof(struct sockaddr_storage),
747         };
748         int s = -1;
749         int rc;
750
751         s = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
752         if (s == -1) {
753                 if (errno != EINTR) {
754                         DBG_ERR("Failed to accept: %s\n", strerror(errno));
755                 }
756                 return;
757         }
758         smb_set_close_on_exec(s);
759
760         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
761         if (rc < 0) {
762                 close(s);
763                 return;
764         }
765
766         rc = getsockname(s, &addr.u.sa, &addr.sa_socklen);
767         if (rc < 0) {
768                 close(s);
769                 return;
770         }
771
772         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &srv_addr);
773         if (rc < 0) {
774                 close(s);
775                 return;
776         }
777
778         DBG_DEBUG("Accepted ncacn_ip_tcp socket %d\n", s);
779
780         dcerpc_ncacn_accept(state->ev_ctx,
781                             state->msg_ctx,
782                             NCACN_IP_TCP,
783                             "IP",
784                             cli_addr,
785                             srv_addr,
786                             s,
787                             state->disconnect_fn,
788                             state->termination_fn,
789                             state->termination_data);
790 }
791
792 /********************************************************************
793  * Start listening on the ncalrpc socket
794  ********************************************************************/
795
796 static void dcesrv_ncalrpc_listener(struct tevent_context *ev,
797                                     struct tevent_fd *fde,
798                                     uint16_t flags,
799                                     void *private_data);
800
801 NTSTATUS dcesrv_create_ncalrpc_socket(const char *name, int *out_fd)
802 {
803         int fd = -1;
804         NTSTATUS status;
805
806         if (name == NULL) {
807                 name = "DEFAULT";
808         }
809
810         if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
811                 status = map_nt_error_from_unix_common(errno);
812                 DBG_ERR("Failed to create ncalrpc directory '%s': %s\n",
813                         lp_ncalrpc_dir(), strerror(errno));
814                 goto out;
815         }
816
817         fd = create_pipe_sock(lp_ncalrpc_dir(), name, 0755);
818         if (fd == -1) {
819                 status = map_nt_error_from_unix_common(errno);
820                 DBG_ERR("Failed to create ncalrpc socket '%s/%s': %s\n",
821                         lp_ncalrpc_dir(), name, strerror(errno));
822                 goto out;
823         }
824
825         DBG_DEBUG("Opened ncalrpc socket fd '%d' for '%s/%s'\n",
826                   fd, lp_ncalrpc_dir(), name);
827
828         *out_fd = fd;
829
830         return NT_STATUS_OK;
831
832 out:
833         return status;
834 }
835
836 NTSTATUS dcesrv_setup_ncalrpc_socket(struct tevent_context *ev_ctx,
837                                      struct messaging_context *msg_ctx,
838                                      const char *name,
839                                      dcerpc_ncacn_disconnect_fn fn)
840 {
841         struct dcerpc_ncacn_listen_state *state;
842         struct tevent_fd *fde;
843         int rc;
844         NTSTATUS status;
845
846         state = talloc_zero(ev_ctx, struct dcerpc_ncacn_listen_state);
847         if (state == NULL) {
848                 DBG_ERR("Out of memory\n");
849                 return NT_STATUS_NO_MEMORY;
850         }
851
852         state->fd = -1;
853         state->disconnect_fn = fn;
854
855         if (name == NULL) {
856                 name = "DEFAULT";
857         }
858
859         state->ep.name = talloc_strdup(state, name);
860         if (state->ep.name == NULL) {
861                 DBG_ERR("Out of memory\n");
862                 talloc_free(state);
863                 return NT_STATUS_NO_MEMORY;
864         }
865
866         status = dcesrv_create_ncalrpc_socket(name, &state->fd);
867         if (!NT_STATUS_IS_OK(status)) {
868                 DBG_ERR("Failed to create ncalrpc socket: %s\n",
869                         nt_errstr(status));
870                 goto out;
871         }
872
873         rc = listen(state->fd, 5);
874         if (rc < 0) {
875                 status = map_nt_error_from_unix_common(errno);
876                 DBG_ERR("Failed to listen on ncalrpc socket %s: %s\n",
877                         name, strerror(errno));
878                 goto out;
879         }
880
881         state->ev_ctx = ev_ctx;
882         state->msg_ctx = msg_ctx;
883
884         /* Set server socket to non-blocking for the accept. */
885         set_blocking(state->fd, false);
886
887         errno = 0;
888         fde = tevent_add_fd(state->ev_ctx,
889                             state,
890                             state->fd,
891                             TEVENT_FD_READ,
892                             dcesrv_ncalrpc_listener,
893                             state);
894         if (fde == NULL) {
895                 if (errno == 0) {
896                         errno = ENOMEM;
897                 }
898                 status = map_nt_error_from_unix_common(errno);
899                 DBG_ERR("Failed to add event handler for ncalrpc: %s\n",
900                         strerror(errno));
901                 goto out;
902         }
903
904         tevent_fd_set_auto_close(fde);
905
906         return NT_STATUS_OK;
907 out:
908         if (state->fd != -1) {
909                 close(state->fd);
910         }
911         TALLOC_FREE(state);
912
913         return status;
914 }
915
916 static void dcesrv_ncalrpc_listener(struct tevent_context *ev,
917                                         struct tevent_fd *fde,
918                                         uint16_t flags,
919                                         void *private_data)
920 {
921         struct dcerpc_ncacn_listen_state *state =
922                 talloc_get_type_abort(private_data,
923                                       struct dcerpc_ncacn_listen_state);
924         struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
925         struct samba_sockaddr addr = {
926                 .sa_socklen = sizeof(struct sockaddr_un),
927         };
928         struct samba_sockaddr addr_server = {
929                 .sa_socklen = sizeof(struct sockaddr_un),
930         };
931         int sd = -1;
932         int rc;
933
934         sd = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
935         if (sd == -1) {
936                 if (errno != EINTR) {
937                         DBG_ERR("Failed to accept: %s\n", strerror(errno));
938                 }
939                 return;
940         }
941         smb_set_close_on_exec(sd);
942
943         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
944         if (rc < 0) {
945                 close(sd);
946                 return;
947         }
948
949         rc = getsockname(sd, &addr_server.u.sa, &addr_server.sa_socklen);
950         if (rc < 0) {
951                 close(sd);
952                 return;
953         }
954
955         rc = tsocket_address_bsd_from_samba_sockaddr(state,
956                                                      &addr_server,
957                                                      &srv_addr);
958         if (rc < 0) {
959                 close(sd);
960                 return;
961         }
962
963         DBG_DEBUG("Accepted ncalrpc socket %s (fd: %d)\n",
964                    addr.u.un.sun_path, sd);
965
966         dcerpc_ncacn_accept(state->ev_ctx,
967                             state->msg_ctx,
968                             NCALRPC,
969                             state->ep.name,
970                             cli_addr, srv_addr, sd,
971                             state->disconnect_fn,
972                             state->termination_fn,
973                             state->termination_data);
974 }
975
976 static int dcerpc_ncacn_conn_destructor(struct dcerpc_ncacn_conn *ncacn_conn)
977 {
978         if (ncacn_conn->disconnect_fn != NULL) {
979                 bool ok = ncacn_conn->disconnect_fn(ncacn_conn->p);
980                 if (!ok) {
981                         DBG_WARNING("Failed to call disconnect function\n");
982                 }
983         }
984
985         if (ncacn_conn->termination_fn != NULL) {
986                 ncacn_conn->termination_fn(ncacn_conn->termination_data);
987         }
988
989         return 0;
990 }
991
992 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
993 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
994 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn *ncacn_conn);
995
996 void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
997                          struct messaging_context *msg_ctx,
998                          enum dcerpc_transport_t transport,
999                          const char *name,
1000                          struct tsocket_address *cli_addr,
1001                          struct tsocket_address *srv_addr,
1002                          int s,
1003                          dcerpc_ncacn_disconnect_fn disconnect_fn,
1004                          dcerpc_ncacn_termination_fn termination_fn,
1005                          void *termination_data)
1006 {
1007         struct dcerpc_ncacn_conn *ncacn_conn;
1008         int rc;
1009
1010         DEBUG(10, ("dcerpc_ncacn_accept\n"));
1011
1012         ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
1013         if (ncacn_conn == NULL) {
1014                 DEBUG(0, ("Out of memory!\n"));
1015                 close(s);
1016                 return;
1017         }
1018         talloc_set_destructor(ncacn_conn, dcerpc_ncacn_conn_destructor);
1019
1020         ncacn_conn->transport = transport;
1021         ncacn_conn->ev_ctx = ev_ctx;
1022         ncacn_conn->msg_ctx = msg_ctx;
1023         ncacn_conn->sock = s;
1024         ncacn_conn->disconnect_fn = disconnect_fn;
1025         ncacn_conn->termination_fn = termination_fn;
1026         ncacn_conn->termination_data = termination_data;
1027         if (name != NULL) {
1028                 ncacn_conn->name = talloc_strdup(ncacn_conn, name);
1029                 if (ncacn_conn->name == NULL) {
1030                         DBG_ERR("Out of memory!\n");
1031                         talloc_free(ncacn_conn);
1032                         close(s);
1033                         return;
1034                 }
1035         }
1036
1037         ncacn_conn->remote_client_addr = talloc_move(ncacn_conn, &cli_addr);
1038         if (tsocket_address_is_inet(ncacn_conn->remote_client_addr, "ip")) {
1039                 ncacn_conn->remote_client_name =
1040                         tsocket_address_inet_addr_string(ncacn_conn->remote_client_addr,
1041                                                          ncacn_conn);
1042         } else {
1043                 ncacn_conn->remote_client_name =
1044                         tsocket_address_unix_path(ncacn_conn->remote_client_addr,
1045                                                   ncacn_conn);
1046         }
1047         if (ncacn_conn->remote_client_name == NULL) {
1048                 DEBUG(0, ("Out of memory obtaining remote socket address as a string!\n"));
1049                 talloc_free(ncacn_conn);
1050                 close(s);
1051                 return;
1052         }
1053
1054         if (srv_addr != NULL) {
1055                 ncacn_conn->local_server_addr = talloc_move(ncacn_conn, &srv_addr);
1056
1057                 if (tsocket_address_is_inet(ncacn_conn->local_server_addr, "ip")) {
1058                         ncacn_conn->local_server_name =
1059                                 tsocket_address_inet_addr_string(ncacn_conn->local_server_addr,
1060                                                                  ncacn_conn);
1061                 } else {
1062                         ncacn_conn->local_server_name =
1063                                 tsocket_address_unix_path(ncacn_conn->local_server_addr,
1064                                                           ncacn_conn);
1065                 }
1066                 if (ncacn_conn->local_server_name == NULL) {
1067                         DEBUG(0, ("Out of memory obtaining local socket address as a string!\n"));
1068                         talloc_free(ncacn_conn);
1069                         close(s);
1070                         return;
1071                 }
1072         }
1073
1074         rc = set_blocking(s, false);
1075         if (rc < 0) {
1076                 DBG_WARNING("Failed to set dcerpc socket to non-blocking\n");
1077                 talloc_free(ncacn_conn);
1078                 close(s);
1079                 return;
1080         }
1081
1082         /*
1083          * As soon as we have tstream_bsd_existing_socket set up it will
1084          * take care of closing the socket.
1085          */
1086         rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
1087         if (rc < 0) {
1088                 DBG_WARNING("Failed to create tstream socket for dcerpc\n");
1089                 talloc_free(ncacn_conn);
1090                 close(s);
1091                 return;
1092         }
1093
1094         dcesrv_ncacn_accept_step2(ncacn_conn);
1095 }
1096
1097 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn *ncacn_conn)
1098 {
1099         struct tevent_req *subreq = NULL;
1100         char *pipe_name = NULL;
1101         uid_t uid;
1102         gid_t gid;
1103         int rc;
1104         int sys_errno;
1105
1106         switch (ncacn_conn->transport) {
1107                 case NCACN_IP_TCP:
1108                         pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
1109                                                            ncacn_conn);
1110                         if (pipe_name == NULL) {
1111                                 talloc_free(ncacn_conn);
1112                                 return;
1113                         }
1114
1115                         break;
1116                 case NCALRPC:
1117                         rc = getpeereid(ncacn_conn->sock, &uid, &gid);
1118                         if (rc < 0) {
1119                                 DEBUG(2, ("Failed to get ncalrpc connecting "
1120                                           "uid - %s!\n", strerror(errno)));
1121                         } else {
1122                                 if (uid == sec_initial_uid()) {
1123                                         TALLOC_FREE(ncacn_conn->remote_client_addr);
1124
1125                                         rc = tsocket_address_unix_from_path(ncacn_conn,
1126                                                                             AS_SYSTEM_MAGIC_PATH_TOKEN,
1127                                                                             &ncacn_conn->remote_client_addr);
1128                                         if (rc < 0) {
1129                                                 DEBUG(0, ("Out of memory building magic ncalrpc_as_system path!\n"));
1130                                                 talloc_free(ncacn_conn);
1131                                                 return;
1132                                         }
1133
1134                                         TALLOC_FREE(ncacn_conn->remote_client_name);
1135                                         ncacn_conn->remote_client_name
1136                                                 = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
1137                                                                             ncacn_conn);
1138                                         if (ncacn_conn->remote_client_name == NULL) {
1139                                                 DEBUG(0, ("Out of memory getting magic ncalrpc_as_system string!\n"));
1140                                                 talloc_free(ncacn_conn);
1141                                                 return;
1142                                         }
1143                                 }
1144                         }
1145
1146                         FALL_THROUGH;
1147                 case NCACN_NP:
1148                         pipe_name = talloc_strdup(ncacn_conn,
1149                                                   ncacn_conn->name);
1150                         if (pipe_name == NULL) {
1151                                 talloc_free(ncacn_conn);
1152                                 return;
1153                         }
1154                         break;
1155                 default:
1156                         DEBUG(0, ("unknown dcerpc transport: %u!\n",
1157                                   ncacn_conn->transport));
1158                         talloc_free(ncacn_conn);
1159                         return;
1160         }
1161
1162         if (ncacn_conn->session_info == NULL) {
1163                 NTSTATUS status;
1164
1165                 status = make_session_info_anonymous(ncacn_conn,
1166                                                      &ncacn_conn->session_info);
1167                 if (!NT_STATUS_IS_OK(status)) {
1168                         DEBUG(2, ("Failed to create "
1169                                   "make_session_info_anonymous - %s\n",
1170                                   nt_errstr(status)));
1171                         talloc_free(ncacn_conn);
1172                         return;
1173                 }
1174         }
1175
1176         rc = make_server_pipes_struct(ncacn_conn,
1177                                       ncacn_conn->msg_ctx,
1178                                       pipe_name,
1179                                       ncacn_conn->transport,
1180                                       ncacn_conn->remote_client_addr,
1181                                       ncacn_conn->local_server_addr,
1182                                       &ncacn_conn->session_info,
1183                                       &ncacn_conn->p,
1184                                       &sys_errno);
1185         if (rc < 0) {
1186                 DEBUG(2, ("Failed to create pipe struct - %s",
1187                           strerror(sys_errno)));
1188                 talloc_free(ncacn_conn);
1189                 return;
1190         }
1191
1192         ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1193                                                         "dcerpc send queue");
1194         if (ncacn_conn->send_queue == NULL) {
1195                 DEBUG(0, ("Out of memory building dcerpc send queue!\n"));
1196                 talloc_free(ncacn_conn);
1197                 return;
1198         }
1199
1200         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1201                                                ncacn_conn->ev_ctx,
1202                                                ncacn_conn->tstream);
1203         if (subreq == NULL) {
1204                 DEBUG(2, ("Failed to send ncacn packet\n"));
1205                 talloc_free(ncacn_conn);
1206                 return;
1207         }
1208
1209         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1210
1211         DEBUG(10, ("dcerpc_ncacn_accept done\n"));
1212
1213         return;
1214 }
1215
1216 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1217 {
1218         struct dcerpc_ncacn_conn *ncacn_conn =
1219                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1220
1221         struct _output_data *out = &ncacn_conn->p->out_data;
1222         DATA_BLOB recv_buffer = data_blob_null;
1223         struct ncacn_packet *pkt;
1224         uint32_t to_send;
1225         NTSTATUS status;
1226         bool ok;
1227
1228         status = dcerpc_read_ncacn_packet_recv(subreq, ncacn_conn, &pkt, &recv_buffer);
1229         TALLOC_FREE(subreq);
1230         if (!NT_STATUS_IS_OK(status)) {
1231                 goto fail;
1232         }
1233
1234         /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
1235         ncacn_conn->p->in_data.pdu_needed_len = 0;
1236         ncacn_conn->p->in_data.pdu = recv_buffer;
1237         if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
1238                 ncacn_conn->p->endian = RPC_LITTLE_ENDIAN;
1239         } else {
1240                 ncacn_conn->p->endian = RPC_BIG_ENDIAN;
1241         }
1242         DEBUG(10, ("PDU is in %s Endian format!\n",
1243                    ncacn_conn->p->endian ? "Big" : "Little"));
1244         process_complete_pdu(ncacn_conn->p, pkt);
1245
1246         /* reset pipe state and free PDU */
1247         ncacn_conn->p->in_data.pdu.length = 0;
1248         talloc_free(recv_buffer.data);
1249         talloc_free(pkt);
1250
1251         /*
1252          * This is needed because of the way DCERPC binds work in the RPC
1253          * marshalling code
1254          */
1255         to_send = out->frag.length - out->current_pdu_sent;
1256         if (to_send > 0) {
1257
1258                 DEBUG(10, ("Current_pdu_len = %u, "
1259                            "current_pdu_sent = %u "
1260                            "Returning %u bytes\n",
1261                            (unsigned int)out->frag.length,
1262                            (unsigned int)out->current_pdu_sent,
1263                            (unsigned int)to_send));
1264
1265                 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1266                 if (ncacn_conn->iov == NULL) {
1267                         status = NT_STATUS_NO_MEMORY;
1268                         DEBUG(3, ("Out of memory!\n"));
1269                         goto fail;
1270                 }
1271                 ncacn_conn->count = 1;
1272
1273                 ncacn_conn->iov[0].iov_base = out->frag.data
1274                                             + out->current_pdu_sent;
1275                 ncacn_conn->iov[0].iov_len = to_send;
1276
1277                 out->current_pdu_sent += to_send;
1278         }
1279
1280         /*
1281          * This condition is false for bind packets, or when we haven't yet got
1282          * a full request, and need to wait for more data from the client
1283          */
1284         while (out->data_sent_length < out->rdata.length) {
1285                 ok = create_next_pdu(ncacn_conn->p);
1286                 if (!ok) {
1287                         DEBUG(3, ("Failed to create next PDU!\n"));
1288                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
1289                         goto fail;
1290                 }
1291
1292                 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1293                                                  ncacn_conn->iov,
1294                                                  struct iovec,
1295                                                  ncacn_conn->count + 1);
1296                 if (ncacn_conn->iov == NULL) {
1297                         DEBUG(3, ("Out of memory!\n"));
1298                         status = NT_STATUS_NO_MEMORY;
1299                         goto fail;
1300                 }
1301
1302                 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1303                 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1304
1305                 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1306                            (unsigned int) ncacn_conn->count,
1307                            (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1308                 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1309                               ncacn_conn->iov[ncacn_conn->count].iov_len);
1310                 ncacn_conn->count++;
1311         }
1312
1313         /*
1314          * We still don't have a complete request, go back and wait for more
1315          * data.
1316          */
1317         if (ncacn_conn->count == 0) {
1318                 /* Wait for the next packet */
1319                 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1320                                                        ncacn_conn->ev_ctx,
1321                                                        ncacn_conn->tstream);
1322                 if (subreq == NULL) {
1323                         DEBUG(2, ("Failed to start receiving packets\n"));
1324                         status = NT_STATUS_NO_MEMORY;
1325                         goto fail;
1326                 }
1327                 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1328                 return;
1329         }
1330
1331         DEBUG(10, ("Sending a total of %u bytes\n",
1332                    (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1333
1334         subreq = tstream_writev_queue_send(ncacn_conn,
1335                                            ncacn_conn->ev_ctx,
1336                                            ncacn_conn->tstream,
1337                                            ncacn_conn->send_queue,
1338                                            ncacn_conn->iov,
1339                                            ncacn_conn->count);
1340         if (subreq == NULL) {
1341                 DEBUG(2, ("Failed to send packet\n"));
1342                 status = NT_STATUS_NO_MEMORY;
1343                 goto fail;
1344         }
1345
1346         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1347         return;
1348
1349 fail:
1350         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1351                   ncacn_conn->remote_client_name, nt_errstr(status)));
1352
1353         /* Terminate client connection */
1354         talloc_free(ncacn_conn);
1355         return;
1356 }
1357
1358 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1359 {
1360         struct dcerpc_ncacn_conn *ncacn_conn =
1361                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1362         NTSTATUS status = NT_STATUS_OK;
1363         int sys_errno;
1364         int rc;
1365
1366         rc = tstream_writev_queue_recv(subreq, &sys_errno);
1367         TALLOC_FREE(subreq);
1368         if (rc < 0) {
1369                 DEBUG(2, ("Writev failed!\n"));
1370                 status = map_nt_error_from_unix(sys_errno);
1371                 goto fail;
1372         }
1373
1374         if (ncacn_conn->p->fault_state != 0) {
1375                 DEBUG(2, ("Disconnect after fault\n"));
1376                 sys_errno = EINVAL;
1377                 goto fail;
1378         }
1379
1380         /* clear out any data that may have been left around */
1381         ncacn_conn->count = 0;
1382         TALLOC_FREE(ncacn_conn->iov);
1383         data_blob_free(&ncacn_conn->p->in_data.data);
1384         data_blob_free(&ncacn_conn->p->out_data.frag);
1385         data_blob_free(&ncacn_conn->p->out_data.rdata);
1386
1387         talloc_free_children(ncacn_conn->p->mem_ctx);
1388
1389         /* Wait for the next packet */
1390         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1391                                                ncacn_conn->ev_ctx,
1392                                                ncacn_conn->tstream);
1393         if (subreq == NULL) {
1394                 DEBUG(2, ("Failed to start receiving packets\n"));
1395                 status = NT_STATUS_NO_MEMORY;
1396                 goto fail;
1397         }
1398
1399         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1400         return;
1401
1402 fail:
1403         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1404                   ncacn_conn->remote_client_name, nt_errstr(status)));
1405
1406         /* Terminate client connection */
1407         talloc_free(ncacn_conn);
1408         return;
1409 }
1410
1411 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */