s4:ntvfs/ipc: replace unnesessary talloc_reference() by a simple talloc_strdup()
[ira/wip.git] / source4 / ntvfs / ipc / vfs_ipc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    default IPC$ NTVFS backend
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Stefan (metze) Metzmacher 2004-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   this implements the IPC$ backend, called by the NTVFS subsystem to
23   handle requests on IPC$ shares
24 */
25
26
27 #include "includes.h"
28 #include "../lib/util/dlinklist.h"
29 #include "ntvfs/ntvfs.h"
30 #include "libcli/rap/rap.h"
31 #include "ntvfs/ipc/proto.h"
32 #include "rpc_server/dcerpc_server.h"
33 #include "libcli/raw/ioctl.h"
34 #include "param/param.h"
35
36 /* this is the private structure used to keep the state of an open
37    ipc$ connection. It needs to keep information about all open
38    pipes */
39 struct ipc_private {
40         struct ntvfs_module_context *ntvfs;
41
42         struct dcesrv_context *dcesrv;
43
44         /* a list of open pipes */
45         struct pipe_state {
46                 struct pipe_state *next, *prev;
47                 struct ipc_private *ipriv;
48                 const char *pipe_name;
49                 struct ntvfs_handle *handle;
50                 struct dcesrv_connection *dce_conn;
51                 uint16_t ipc_state;
52         } *pipe_list;
53 };
54
55
56 /*
57   find a open pipe give a file handle
58 */
59 static struct pipe_state *pipe_state_find(struct ipc_private *ipriv, struct ntvfs_handle *handle)
60 {
61         struct pipe_state *s;
62         void *p;
63
64         p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs);
65         if (!p) return NULL;
66
67         s = talloc_get_type(p, struct pipe_state);
68         if (!s) return NULL;
69
70         return s;
71 }
72
73 /*
74   find a open pipe give a wire fnum
75 */
76 static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct ntvfs_request *req, const DATA_BLOB *key)
77 {
78         struct ntvfs_handle *h;
79
80         h = ntvfs_handle_search_by_wire_key(ipriv->ntvfs, req, key);
81         if (!h) return NULL;
82
83         return pipe_state_find(ipriv, h);
84 }
85
86
87 /*
88   connect to a share - always works 
89 */
90 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
91                             struct ntvfs_request *req,
92                             union smb_tcon* tcon)
93 {
94         NTSTATUS status;
95         struct ipc_private *ipriv;
96         const char *sharename;
97
98         switch (tcon->generic.level) {
99         case RAW_TCON_TCON:
100                 sharename = tcon->tcon.in.service;
101                 break;
102         case RAW_TCON_TCONX:
103                 sharename = tcon->tconx.in.path;
104                 break;
105         case RAW_TCON_SMB2:
106                 sharename = tcon->smb2.in.path;
107                 break;
108         default:
109                 return NT_STATUS_INVALID_LEVEL;
110         }
111
112         if (strncmp(sharename, "\\\\", 2) == 0) {
113                 char *p = strchr(sharename+2, '\\');
114                 if (p) {
115                         sharename = p + 1;
116                 }
117         }
118
119         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
120         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
121
122         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
123         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
124
125         if (tcon->generic.level == RAW_TCON_TCONX) {
126                 tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
127                 tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
128         }
129
130         /* prepare the private state for this connection */
131         ipriv = talloc(ntvfs, struct ipc_private);
132         NT_STATUS_HAVE_NO_MEMORY(ipriv);
133
134         ntvfs->private_data = ipriv;
135
136         ipriv->ntvfs = ntvfs;
137         ipriv->pipe_list = NULL;
138
139         /* setup the DCERPC server subsystem */
140         status = dcesrv_init_ipc_context(ipriv, ntvfs->ctx->lp_ctx, &ipriv->dcesrv);
141         NT_STATUS_NOT_OK_RETURN(status);
142
143         return NT_STATUS_OK;
144 }
145
146 /*
147   disconnect from a share
148 */
149 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
150 {
151         return NT_STATUS_OK;
152 }
153
154 /*
155   delete a file
156 */
157 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
158                            struct ntvfs_request *req,
159                            union smb_unlink *unl)
160 {
161         return NT_STATUS_ACCESS_DENIED;
162 }
163
164 /*
165   check if a directory exists
166 */
167 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
168                             struct ntvfs_request *req,
169                             union smb_chkpath *cp)
170 {
171         return NT_STATUS_ACCESS_DENIED;
172 }
173
174 /*
175   return info on a pathname
176 */
177 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
178                               struct ntvfs_request *req, union smb_fileinfo *info)
179 {
180         switch (info->generic.level) {
181         case  RAW_FILEINFO_GENERIC:
182                 return NT_STATUS_INVALID_DEVICE_REQUEST;
183         case RAW_FILEINFO_GETATTR:
184                 return NT_STATUS_ACCESS_DENIED;
185         default:
186                 return ntvfs_map_qpathinfo(ntvfs, req, info);
187         }
188 }
189
190 /*
191   set info on a pathname
192 */
193 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
194                                 struct ntvfs_request *req, union smb_setfileinfo *st)
195 {
196         return NT_STATUS_ACCESS_DENIED;
197 }
198
199
200 /*
201   destroy a open pipe structure
202 */
203 static int ipc_fd_destructor(struct pipe_state *p)
204 {
205         DLIST_REMOVE(p->ipriv->pipe_list, p);
206         ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs);
207         return 0;
208 }
209
210 static struct socket_address *ipc_get_my_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
211 {
212         struct ipc_private *ipriv = dce_conn->transport.private_data;
213
214         return ntvfs_get_my_addr(ipriv->ntvfs, mem_ctx);
215 }
216
217 static struct socket_address *ipc_get_peer_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
218 {
219         struct ipc_private *ipriv = dce_conn->transport.private_data;
220
221         return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
222 }
223
224 /*
225   open a file backend - used for MSRPC pipes
226 */
227 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
228                                  struct ntvfs_request *req, const char *fname, 
229                                  struct pipe_state **ps)
230 {
231         struct pipe_state *p;
232         NTSTATUS status;
233         struct dcerpc_binding *ep_description;
234         struct ipc_private *ipriv = ntvfs->private_data;
235         struct ntvfs_handle *h;
236
237         status = ntvfs_handle_new(ntvfs, req, &h);
238         NT_STATUS_NOT_OK_RETURN(status);
239
240         p = talloc(h, struct pipe_state);
241         NT_STATUS_HAVE_NO_MEMORY(p);
242
243         ep_description = talloc(req, struct dcerpc_binding);
244         NT_STATUS_HAVE_NO_MEMORY(ep_description);
245
246         while (fname[0] == '\\') fname++;
247
248         p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
249         NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
250
251         p->handle = h;
252         p->ipc_state = 0x5ff;
253
254         /*
255           we're all set, now ask the dcerpc server subsystem to open the 
256           endpoint. At this stage the pipe isn't bound, so we don't
257           know what interface the user actually wants, just that they want
258           one of the interfaces attached to this pipe endpoint.
259         */
260         ep_description->transport = NCACN_NP;
261         ep_description->endpoint = talloc_strdup(ep_description, p->pipe_name);
262         NT_STATUS_HAVE_NO_MEMORY(ep_description->endpoint);
263
264         /* The session info is refcount-increased in the 
265          * dcesrv_endpoint_search_connect() function
266          */
267         status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
268                                                 p,
269                                                 ep_description, 
270                                                 h->session_info,
271                                                 ntvfs->ctx->event_ctx,
272                                                 ntvfs->ctx->msg_ctx,
273                                                 ntvfs->ctx->server_id,
274                                                 0,
275                                                 &p->dce_conn);
276         NT_STATUS_NOT_OK_RETURN(status);
277
278         p->dce_conn->transport.private_data             = ipriv;
279         p->dce_conn->transport.report_output_data       = NULL;
280         p->dce_conn->transport.get_my_addr              = ipc_get_my_addr;
281         p->dce_conn->transport.get_peer_addr            = ipc_get_peer_addr;
282         
283         DLIST_ADD(ipriv->pipe_list, p);
284
285         p->ipriv = ipriv;
286
287         talloc_set_destructor(p, ipc_fd_destructor);
288
289         status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
290         NT_STATUS_NOT_OK_RETURN(status);
291
292         *ps = p;
293         return NT_STATUS_OK;
294 }
295
296 /*
297   open a file with ntcreatex - used for MSRPC pipes
298 */
299 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
300                                    struct ntvfs_request *req, union smb_open *oi)
301 {
302         struct pipe_state *p;
303         NTSTATUS status;
304
305         status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
306         if (!NT_STATUS_IS_OK(status)) {
307                 return status;
308         }
309
310         ZERO_STRUCT(oi->ntcreatex.out);
311         oi->ntcreatex.out.file.ntvfs= p->handle;
312         oi->ntcreatex.out.ipc_state = p->ipc_state;
313         oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
314
315         return status;
316 }
317
318 /*
319   open a file with openx - used for MSRPC pipes
320 */
321 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
322                                struct ntvfs_request *req, union smb_open *oi)
323 {
324         struct pipe_state *p;
325         NTSTATUS status;
326         const char *fname = oi->openx.in.fname;
327
328         status = ipc_open_generic(ntvfs, req, fname, &p);
329         if (!NT_STATUS_IS_OK(status)) {
330                 return status;
331         }
332
333         ZERO_STRUCT(oi->openx.out);
334         oi->openx.out.file.ntvfs= p->handle;
335         oi->openx.out.ftype     = 2;
336         oi->openx.out.devstate  = p->ipc_state;
337         
338         return status;
339 }
340
341 /*
342   open a file with SMB2 Create - used for MSRPC pipes
343 */
344 static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
345                               struct ntvfs_request *req, union smb_open *oi)
346 {
347         struct pipe_state *p;
348         NTSTATUS status;
349
350         status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
351         NT_STATUS_NOT_OK_RETURN(status);
352
353         ZERO_STRUCT(oi->smb2.out);
354         oi->smb2.out.file.ntvfs         = p->handle;
355         oi->smb2.out.oplock_level       = oi->smb2.in.oplock_level;
356         oi->smb2.out.create_action      = NTCREATEX_ACTION_EXISTED;
357         oi->smb2.out.create_time        = 0;
358         oi->smb2.out.access_time        = 0;
359         oi->smb2.out.write_time         = 0;
360         oi->smb2.out.change_time        = 0;
361         oi->smb2.out.alloc_size         = 4096;
362         oi->smb2.out.size               = 0;
363         oi->smb2.out.file_attr          = FILE_ATTRIBUTE_NORMAL;
364         oi->smb2.out.reserved2          = 0;
365
366         return status;
367 }
368
369 /*
370   open a file - used for MSRPC pipes
371 */
372 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
373                                 struct ntvfs_request *req, union smb_open *oi)
374 {
375         NTSTATUS status;
376
377         switch (oi->generic.level) {
378         case RAW_OPEN_NTCREATEX:
379                 status = ipc_open_ntcreatex(ntvfs, req, oi);
380                 break;
381         case RAW_OPEN_OPENX:
382                 status = ipc_open_openx(ntvfs, req, oi);
383                 break;
384         case RAW_OPEN_SMB2:
385                 status = ipc_open_smb2(ntvfs, req, oi);
386                 break;
387         default:
388                 status = NT_STATUS_NOT_SUPPORTED;
389                 break;
390         }
391
392         return status;
393 }
394
395 /*
396   create a directory
397 */
398 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
399                           struct ntvfs_request *req, union smb_mkdir *md)
400 {
401         return NT_STATUS_ACCESS_DENIED;
402 }
403
404 /*
405   remove a directory
406 */
407 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
408                           struct ntvfs_request *req, struct smb_rmdir *rd)
409 {
410         return NT_STATUS_ACCESS_DENIED;
411 }
412
413 /*
414   rename a set of files
415 */
416 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
417                            struct ntvfs_request *req, union smb_rename *ren)
418 {
419         return NT_STATUS_ACCESS_DENIED;
420 }
421
422 /*
423   copy a set of files
424 */
425 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
426                          struct ntvfs_request *req, struct smb_copy *cp)
427 {
428         return NT_STATUS_ACCESS_DENIED;
429 }
430
431 static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
432 {
433         DATA_BLOB *blob = private_data;
434
435         if (out->length < blob->length) {
436                 blob->length = out->length;
437         }
438         memcpy(blob->data, out->data, blob->length);
439         *nwritten = blob->length;
440         return NT_STATUS_OK;
441 }
442
443 /*
444   read from a file
445 */
446 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
447                          struct ntvfs_request *req, union smb_read *rd)
448 {
449         struct ipc_private *ipriv = ntvfs->private_data;
450         DATA_BLOB data;
451         struct pipe_state *p;
452         NTSTATUS status = NT_STATUS_OK;
453
454         if (rd->generic.level != RAW_READ_GENERIC) {
455                 return ntvfs_map_read(ntvfs, req, rd);
456         }
457
458         p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs);
459         if (!p) {
460                 return NT_STATUS_INVALID_HANDLE;
461         }
462
463         data.length = rd->readx.in.maxcnt;
464         data.data = rd->readx.out.data;
465         if (data.length > UINT16_MAX) {
466                 data.length = UINT16_MAX;
467         }
468
469         if (data.length != 0) {
470                 status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
471                 if (NT_STATUS_IS_ERR(status)) {
472                         return status;
473                 }
474         }
475
476         rd->readx.out.remaining = 0;
477         rd->readx.out.compaction_mode = 0;
478         rd->readx.out.nread = data.length;
479
480         return status;
481 }
482
483 /*
484   write to a file
485 */
486 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
487                           struct ntvfs_request *req, union smb_write *wr)
488 {
489         struct ipc_private *ipriv = ntvfs->private_data;
490         DATA_BLOB data;
491         struct pipe_state *p;
492         NTSTATUS status;
493
494         if (wr->generic.level != RAW_WRITE_GENERIC) {
495                 return ntvfs_map_write(ntvfs, req, wr);
496         }
497
498         data.data = discard_const_p(void, wr->writex.in.data);
499         data.length = wr->writex.in.count;
500
501         p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs);
502         if (!p) {
503                 return NT_STATUS_INVALID_HANDLE;
504         }
505
506         status = dcesrv_input(p->dce_conn, &data);
507         if (!NT_STATUS_IS_OK(status)) {
508                 return status;
509         }
510
511         wr->writex.out.nwritten = data.length;
512         wr->writex.out.remaining = 0;
513
514         return NT_STATUS_OK;
515 }
516
517 /*
518   seek in a file
519 */
520 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
521                          struct ntvfs_request *req,
522                          union smb_seek *io)
523 {
524         return NT_STATUS_ACCESS_DENIED;
525 }
526
527 /*
528   flush a file
529 */
530 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
531                           struct ntvfs_request *req,
532                           union smb_flush *io)
533 {
534         return NT_STATUS_ACCESS_DENIED;
535 }
536
537 /*
538   close a file
539 */
540 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
541                           struct ntvfs_request *req, union smb_close *io)
542 {
543         struct ipc_private *ipriv = ntvfs->private_data;
544         struct pipe_state *p;
545
546         if (io->generic.level != RAW_CLOSE_CLOSE) {
547                 return ntvfs_map_close(ntvfs, req, io);
548         }
549
550         p = pipe_state_find(ipriv, io->close.in.file.ntvfs);
551         if (!p) {
552                 return NT_STATUS_INVALID_HANDLE;
553         }
554
555         talloc_free(p);
556
557         return NT_STATUS_OK;
558 }
559
560 /*
561   exit - closing files
562 */
563 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
564                          struct ntvfs_request *req)
565 {
566         struct ipc_private *ipriv = ntvfs->private_data;
567         struct pipe_state *p, *next;
568         
569         for (p=ipriv->pipe_list; p; p=next) {
570                 next = p->next;
571                 if (p->handle->session_info == req->session_info &&
572                     p->handle->smbpid == req->smbpid) {
573                         talloc_free(p);
574                 }
575         }
576
577         return NT_STATUS_OK;
578 }
579
580 /*
581   logoff - closing files open by the user
582 */
583 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
584                            struct ntvfs_request *req)
585 {
586         struct ipc_private *ipriv = ntvfs->private_data;
587         struct pipe_state *p, *next;
588         
589         for (p=ipriv->pipe_list; p; p=next) {
590                 next = p->next;
591                 if (p->handle->session_info == req->session_info) {
592                         talloc_free(p);
593                 }
594         }
595
596         return NT_STATUS_OK;
597 }
598
599 /*
600   setup for an async call
601 */
602 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
603                                 struct ntvfs_request *req,
604                                 void *private_data)
605 {
606         return NT_STATUS_OK;
607 }
608
609 /*
610   cancel an async call
611 */
612 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
613                            struct ntvfs_request *req)
614 {
615         return NT_STATUS_UNSUCCESSFUL;
616 }
617
618 /*
619   lock a byte range
620 */
621 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
622                          struct ntvfs_request *req, union smb_lock *lck)
623 {
624         return NT_STATUS_ACCESS_DENIED;
625 }
626
627 /*
628   set info on a open file
629 */
630 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
631                                 struct ntvfs_request *req, union smb_setfileinfo *info)
632 {
633         return NT_STATUS_ACCESS_DENIED;
634 }
635
636 /*
637   query info on a open file
638 */
639 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
640                               struct ntvfs_request *req, union smb_fileinfo *info)
641 {
642         struct ipc_private *ipriv = ntvfs->private_data;
643         struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs);
644         if (!p) {
645                 return NT_STATUS_INVALID_HANDLE;
646         }
647         switch (info->generic.level) {
648         case RAW_FILEINFO_GENERIC: 
649         {
650                 ZERO_STRUCT(info->generic.out);
651                 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL;
652                 info->generic.out.fname.s = strrchr(p->pipe_name, '\\');
653                 info->generic.out.alloc_size = 4096;
654                 info->generic.out.nlink = 1;
655                 /* What the heck?  Match Win2k3: IPC$ pipes are delete pending */
656                 info->generic.out.delete_pending = 1;
657                 return NT_STATUS_OK;
658         }
659         case RAW_FILEINFO_ALT_NAME_INFO:
660         case RAW_FILEINFO_ALT_NAME_INFORMATION:
661         case RAW_FILEINFO_STREAM_INFO:
662         case RAW_FILEINFO_STREAM_INFORMATION:
663         case RAW_FILEINFO_COMPRESSION_INFO:
664         case RAW_FILEINFO_COMPRESSION_INFORMATION:
665         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
666         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
667                 return NT_STATUS_INVALID_PARAMETER;
668         case  RAW_FILEINFO_ALL_EAS:
669                 return NT_STATUS_ACCESS_DENIED;
670         default:
671                 return ntvfs_map_qfileinfo(ntvfs, req, info);
672         }
673         
674         return NT_STATUS_ACCESS_DENIED;
675 }
676
677
678 /*
679   return filesystem info
680 */
681 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
682                            struct ntvfs_request *req, union smb_fsinfo *fs)
683 {
684         return NT_STATUS_ACCESS_DENIED;
685 }
686
687 /*
688   return print queue info
689 */
690 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
691                         struct ntvfs_request *req, union smb_lpq *lpq)
692 {
693         return NT_STATUS_ACCESS_DENIED;
694 }
695
696 /* 
697    list files in a directory matching a wildcard pattern
698 */
699 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
700                           struct ntvfs_request *req, union smb_search_first *io,
701                           void *search_private, 
702                           bool (*callback)(void *, const union smb_search_data *))
703 {
704         return NT_STATUS_ACCESS_DENIED;
705 }
706
707 /* 
708    continue listing files in a directory 
709 */
710 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
711                          struct ntvfs_request *req, union smb_search_next *io,
712                          void *search_private, 
713                          bool (*callback)(void *, const union smb_search_data *))
714 {
715         return NT_STATUS_ACCESS_DENIED;
716 }
717
718 /* 
719    end listing files in a directory 
720 */
721 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
722                           struct ntvfs_request *req, union smb_search_close *io)
723 {
724         return NT_STATUS_ACCESS_DENIED;
725 }
726
727 static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
728 {
729         NTSTATUS status = NT_STATUS_OK;
730         DATA_BLOB *blob = private_data;
731
732         if (out->length > blob->length) {
733                 status = STATUS_BUFFER_OVERFLOW;
734         }
735
736         if (out->length < blob->length) {
737                 blob->length = out->length;
738         }
739         memcpy(blob->data, out->data, blob->length);
740         *nwritten = blob->length;
741         return status;
742 }
743
744 /* SMBtrans - handle a DCERPC command */
745 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
746                                struct ntvfs_request *req, struct smb_trans2 *trans)
747 {
748         struct pipe_state *p;
749         struct ipc_private *ipriv = ntvfs->private_data;
750         NTSTATUS status;
751         DATA_BLOB fnum_key;
752         uint16_t fnum;
753
754         /*
755          * the fnum is in setup[1], a 16 bit value
756          * the setup[*] values are already in host byteorder
757          * but ntvfs_handle_search_by_wire_key() expects
758          * network byteorder
759          */
760         SSVAL(&fnum, 0, trans->in.setup[1]);
761         fnum_key = data_blob_const(&fnum, 2);
762
763         p = pipe_state_find_key(ipriv, req, &fnum_key);
764         if (!p) {
765                 return NT_STATUS_INVALID_HANDLE;
766         }
767
768         trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
769         if (!trans->out.data.data) {
770                 return NT_STATUS_NO_MEMORY;
771         }
772
773         /* pass the data to the dcerpc server. Note that we don't
774            expect this to fail, and things like NDR faults are not
775            reported at this stage. Those sorts of errors happen in the
776            dcesrv_output stage */
777         status = dcesrv_input(p->dce_conn, &trans->in.data);
778         if (!NT_STATUS_IS_OK(status)) {
779                 return status;
780         }
781
782         /*
783           now ask the dcerpc system for some output. This doesn't yet handle
784           async calls. Again, we only expect NT_STATUS_OK. If the call fails then
785           the error is encoded at the dcerpc level
786         */
787         status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
788         if (NT_STATUS_IS_ERR(status)) {
789                 return status;
790         }
791
792         trans->out.setup_count = 0;
793         trans->out.setup = NULL;
794         trans->out.params = data_blob(NULL, 0);
795
796         return status;
797 }
798
799
800 /* SMBtrans - set named pipe state */
801 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
802                                       struct ntvfs_request *req, struct smb_trans2 *trans)
803 {
804         struct ipc_private *ipriv = ntvfs->private_data;
805         struct pipe_state *p;
806         DATA_BLOB fnum_key;
807
808         /* the fnum is in setup[1] */
809         fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
810
811         p = pipe_state_find_key(ipriv, req, &fnum_key);
812         if (!p) {
813                 return NT_STATUS_INVALID_HANDLE;
814         }
815
816         if (trans->in.params.length != 2) {
817                 return NT_STATUS_INVALID_PARAMETER;
818         }
819         p->ipc_state = SVAL(trans->in.params.data, 0);
820
821         trans->out.setup_count = 0;
822         trans->out.setup = NULL;
823         trans->out.params = data_blob(NULL, 0);
824         trans->out.data = data_blob(NULL, 0);
825
826         return NT_STATUS_OK;
827 }
828
829
830 /* SMBtrans - used to provide access to SMB pipes */
831 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
832                                 struct ntvfs_request *req, struct smb_trans2 *trans)
833 {
834         NTSTATUS status;
835
836         if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
837                 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
838
839         if (trans->in.setup_count != 2) {
840                 return NT_STATUS_INVALID_PARAMETER;
841         }
842
843         switch (trans->in.setup[0]) {
844         case TRANSACT_SETNAMEDPIPEHANDLESTATE:
845                 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
846                 break;
847         case TRANSACT_DCERPCCMD:
848                 status = ipc_dcerpc_cmd(ntvfs, req, trans);
849                 break;
850         default:
851                 status = NT_STATUS_INVALID_PARAMETER;
852                 break;
853         }
854
855         return status;
856 }
857
858 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
859                                struct ntvfs_request *req, union smb_ioctl *io)
860 {
861         struct pipe_state *p;
862         struct ipc_private *ipriv = ntvfs->private_data;
863         NTSTATUS status;
864
865         switch (io->smb2.in.function) {
866         case FSCTL_NAMED_PIPE_READ_WRITE:
867                 break;
868
869         default:
870                 return NT_STATUS_FS_DRIVER_REQUIRED;
871         }
872
873         p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs);
874         if (!p) {
875                 return NT_STATUS_INVALID_HANDLE;
876         }
877
878         io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_response_size);
879         NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data);
880
881         /* pass the data to the dcerpc server. Note that we don't
882            expect this to fail, and things like NDR faults are not
883            reported at this stage. Those sorts of errors happen in the
884            dcesrv_output stage */
885         status = dcesrv_input(p->dce_conn, &io->smb2.in.out);
886         NT_STATUS_NOT_OK_RETURN(status);
887
888         /*
889           now ask the dcerpc system for some output. This doesn't yet handle
890           async calls. Again, we only expect NT_STATUS_OK. If the call fails then
891           the error is encoded at the dcerpc level
892         */
893         status = dcesrv_output(p->dce_conn, &io->smb2.out.out, ipc_trans_dcesrv_output);
894         NT_STATUS_IS_ERR_RETURN(status);
895
896         io->smb2.out._pad       = 0;
897         io->smb2.out.function   = io->smb2.in.function;
898         io->smb2.out.unknown2   = 0;
899         io->smb2.out.unknown3   = 0;
900         io->smb2.out.in         = io->smb2.in.out;
901
902         return status;
903 }
904
905 /*
906   ioctl interface
907 */
908 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
909                           struct ntvfs_request *req, union smb_ioctl *io)
910 {
911         switch (io->generic.level) {
912         case RAW_IOCTL_SMB2:
913                 return ipc_ioctl_smb2(ntvfs, req, io);
914
915         case RAW_IOCTL_SMB2_NO_HANDLE:
916                 return NT_STATUS_FS_DRIVER_REQUIRED;
917
918         default:
919                 return NT_STATUS_ACCESS_DENIED;
920         }
921
922         return NT_STATUS_ACCESS_DENIED;
923 }
924
925
926 /*
927   initialialise the IPC backend, registering ourselves with the ntvfs subsystem
928  */
929 NTSTATUS ntvfs_ipc_init(void)
930 {
931         NTSTATUS ret;
932         struct ntvfs_ops ops;
933         NTVFS_CURRENT_CRITICAL_SIZES(vers);
934
935         ZERO_STRUCT(ops);
936         
937         /* fill in the name and type */
938         ops.name = "default";
939         ops.type = NTVFS_IPC;
940
941         /* fill in all the operations */
942         ops.connect = ipc_connect;
943         ops.disconnect = ipc_disconnect;
944         ops.unlink = ipc_unlink;
945         ops.chkpath = ipc_chkpath;
946         ops.qpathinfo = ipc_qpathinfo;
947         ops.setpathinfo = ipc_setpathinfo;
948         ops.open = ipc_open;
949         ops.mkdir = ipc_mkdir;
950         ops.rmdir = ipc_rmdir;
951         ops.rename = ipc_rename;
952         ops.copy = ipc_copy;
953         ops.ioctl = ipc_ioctl;
954         ops.read = ipc_read;
955         ops.write = ipc_write;
956         ops.seek = ipc_seek;
957         ops.flush = ipc_flush;  
958         ops.close = ipc_close;
959         ops.exit = ipc_exit;
960         ops.lock = ipc_lock;
961         ops.setfileinfo = ipc_setfileinfo;
962         ops.qfileinfo = ipc_qfileinfo;
963         ops.fsinfo = ipc_fsinfo;
964         ops.lpq = ipc_lpq;
965         ops.search_first = ipc_search_first;
966         ops.search_next = ipc_search_next;
967         ops.search_close = ipc_search_close;
968         ops.trans = ipc_trans;
969         ops.logoff = ipc_logoff;
970         ops.async_setup = ipc_async_setup;
971         ops.cancel = ipc_cancel;
972
973         /* register ourselves with the NTVFS subsystem. */
974         ret = ntvfs_register(&ops, &vers);
975
976         if (!NT_STATUS_IS_OK(ret)) {
977                 DEBUG(0,("Failed to register IPC backend!\n"));
978                 return ret;
979         }
980
981         return ret;
982 }