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