2 Unix SMB/CIFS implementation.
3 default IPC$ NTVFS backend
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Stefan (metze) Metzmacher 2004-2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 this implements the IPC$ backend, called by the NTVFS subsystem to
23 handle requests on IPC$ shares
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"
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
40 struct ntvfs_module_context *ntvfs;
42 struct dcesrv_context *dcesrv;
44 /* a list of open pipes */
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;
57 find a open pipe give a file handle
59 static struct pipe_state *pipe_state_find(struct ipc_private *ipriv, struct ntvfs_handle *handle)
64 p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs);
67 s = talloc_get_type(p, struct pipe_state);
74 find a open pipe give a wire fnum
76 static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct ntvfs_request *req, const DATA_BLOB *key)
78 struct ntvfs_handle *h;
80 h = ntvfs_handle_search_by_wire_key(ipriv->ntvfs, req, key);
83 return pipe_state_find(ipriv, h);
88 connect to a share - always works
90 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
91 struct ntvfs_request *req,
95 struct ipc_private *ipriv;
96 const char *sharename;
98 switch (tcon->generic.level) {
100 sharename = tcon->tcon.in.service;
103 sharename = tcon->tconx.in.path;
106 sharename = tcon->smb2.in.path;
109 return NT_STATUS_INVALID_LEVEL;
112 if (strncmp(sharename, "\\\\", 2) == 0) {
113 char *p = strchr(sharename+2, '\\');
119 ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
120 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
122 ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
123 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
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;
130 /* prepare the private state for this connection */
131 ipriv = talloc(ntvfs, struct ipc_private);
132 NT_STATUS_HAVE_NO_MEMORY(ipriv);
134 ntvfs->private_data = ipriv;
136 ipriv->ntvfs = ntvfs;
137 ipriv->pipe_list = NULL;
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);
147 disconnect from a share
149 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
157 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
158 struct ntvfs_request *req,
159 union smb_unlink *unl)
161 return NT_STATUS_ACCESS_DENIED;
165 check if a directory exists
167 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
168 struct ntvfs_request *req,
169 union smb_chkpath *cp)
171 return NT_STATUS_ACCESS_DENIED;
175 return info on a pathname
177 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
178 struct ntvfs_request *req, union smb_fileinfo *info)
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;
186 return ntvfs_map_qpathinfo(ntvfs, req, info);
191 set info on a pathname
193 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
194 struct ntvfs_request *req, union smb_setfileinfo *st)
196 return NT_STATUS_ACCESS_DENIED;
201 destroy a open pipe structure
203 static int ipc_fd_destructor(struct pipe_state *p)
205 DLIST_REMOVE(p->ipriv->pipe_list, p);
206 ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs);
210 static struct socket_address *ipc_get_my_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
212 struct ipc_private *ipriv = dce_conn->transport.private_data;
214 return ntvfs_get_my_addr(ipriv->ntvfs, mem_ctx);
217 static struct socket_address *ipc_get_peer_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
219 struct ipc_private *ipriv = dce_conn->transport.private_data;
221 return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
225 open a file backend - used for MSRPC pipes
227 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
228 struct ntvfs_request *req, const char *fname,
229 struct pipe_state **ps)
231 struct pipe_state *p;
233 struct dcerpc_binding *ep_description;
234 struct ipc_private *ipriv = ntvfs->private_data;
235 struct ntvfs_handle *h;
237 status = ntvfs_handle_new(ntvfs, req, &h);
238 NT_STATUS_NOT_OK_RETURN(status);
240 p = talloc(h, struct pipe_state);
241 NT_STATUS_HAVE_NO_MEMORY(p);
243 ep_description = talloc(req, struct dcerpc_binding);
244 NT_STATUS_HAVE_NO_MEMORY(ep_description);
246 while (fname[0] == '\\') fname++;
248 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
249 NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
252 p->ipc_state = 0x5ff;
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.
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);
264 /* The session info is refcount-increased in the
265 * dcesrv_endpoint_search_connect() function
267 status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
271 ntvfs->ctx->event_ctx,
273 ntvfs->ctx->server_id,
276 NT_STATUS_NOT_OK_RETURN(status);
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;
283 DLIST_ADD(ipriv->pipe_list, p);
287 talloc_set_destructor(p, ipc_fd_destructor);
289 status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
290 NT_STATUS_NOT_OK_RETURN(status);
297 open a file with ntcreatex - used for MSRPC pipes
299 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
300 struct ntvfs_request *req, union smb_open *oi)
302 struct pipe_state *p;
305 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
306 if (!NT_STATUS_IS_OK(status)) {
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;
319 open a file with openx - used for MSRPC pipes
321 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
322 struct ntvfs_request *req, union smb_open *oi)
324 struct pipe_state *p;
326 const char *fname = oi->openx.in.fname;
328 status = ipc_open_generic(ntvfs, req, fname, &p);
329 if (!NT_STATUS_IS_OK(status)) {
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;
342 open a file with SMB2 Create - used for MSRPC pipes
344 static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
345 struct ntvfs_request *req, union smb_open *oi)
347 struct pipe_state *p;
350 status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
351 NT_STATUS_NOT_OK_RETURN(status);
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;
370 open a file - used for MSRPC pipes
372 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
373 struct ntvfs_request *req, union smb_open *oi)
377 switch (oi->generic.level) {
378 case RAW_OPEN_NTCREATEX:
379 status = ipc_open_ntcreatex(ntvfs, req, oi);
382 status = ipc_open_openx(ntvfs, req, oi);
385 status = ipc_open_smb2(ntvfs, req, oi);
388 status = NT_STATUS_NOT_SUPPORTED;
398 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
399 struct ntvfs_request *req, union smb_mkdir *md)
401 return NT_STATUS_ACCESS_DENIED;
407 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
408 struct ntvfs_request *req, struct smb_rmdir *rd)
410 return NT_STATUS_ACCESS_DENIED;
414 rename a set of files
416 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
417 struct ntvfs_request *req, union smb_rename *ren)
419 return NT_STATUS_ACCESS_DENIED;
425 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
426 struct ntvfs_request *req, struct smb_copy *cp)
428 return NT_STATUS_ACCESS_DENIED;
431 static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
433 DATA_BLOB *blob = private_data;
435 if (out->length < blob->length) {
436 blob->length = out->length;
438 memcpy(blob->data, out->data, blob->length);
439 *nwritten = blob->length;
446 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
447 struct ntvfs_request *req, union smb_read *rd)
449 struct ipc_private *ipriv = ntvfs->private_data;
451 struct pipe_state *p;
452 NTSTATUS status = NT_STATUS_OK;
454 if (rd->generic.level != RAW_READ_GENERIC) {
455 return ntvfs_map_read(ntvfs, req, rd);
458 p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs);
460 return NT_STATUS_INVALID_HANDLE;
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;
469 if (data.length != 0) {
470 status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
471 if (NT_STATUS_IS_ERR(status)) {
476 rd->readx.out.remaining = 0;
477 rd->readx.out.compaction_mode = 0;
478 rd->readx.out.nread = data.length;
486 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
487 struct ntvfs_request *req, union smb_write *wr)
489 struct ipc_private *ipriv = ntvfs->private_data;
491 struct pipe_state *p;
494 if (wr->generic.level != RAW_WRITE_GENERIC) {
495 return ntvfs_map_write(ntvfs, req, wr);
498 data.data = discard_const_p(void, wr->writex.in.data);
499 data.length = wr->writex.in.count;
501 p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs);
503 return NT_STATUS_INVALID_HANDLE;
506 status = dcesrv_input(p->dce_conn, &data);
507 if (!NT_STATUS_IS_OK(status)) {
511 wr->writex.out.nwritten = data.length;
512 wr->writex.out.remaining = 0;
520 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
521 struct ntvfs_request *req,
524 return NT_STATUS_ACCESS_DENIED;
530 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
531 struct ntvfs_request *req,
534 return NT_STATUS_ACCESS_DENIED;
540 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
541 struct ntvfs_request *req, union smb_close *io)
543 struct ipc_private *ipriv = ntvfs->private_data;
544 struct pipe_state *p;
546 if (io->generic.level != RAW_CLOSE_CLOSE) {
547 return ntvfs_map_close(ntvfs, req, io);
550 p = pipe_state_find(ipriv, io->close.in.file.ntvfs);
552 return NT_STATUS_INVALID_HANDLE;
563 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
564 struct ntvfs_request *req)
566 struct ipc_private *ipriv = ntvfs->private_data;
567 struct pipe_state *p, *next;
569 for (p=ipriv->pipe_list; p; p=next) {
571 if (p->handle->session_info == req->session_info &&
572 p->handle->smbpid == req->smbpid) {
581 logoff - closing files open by the user
583 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
584 struct ntvfs_request *req)
586 struct ipc_private *ipriv = ntvfs->private_data;
587 struct pipe_state *p, *next;
589 for (p=ipriv->pipe_list; p; p=next) {
591 if (p->handle->session_info == req->session_info) {
600 setup for an async call
602 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
603 struct ntvfs_request *req,
612 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
613 struct ntvfs_request *req)
615 return NT_STATUS_UNSUCCESSFUL;
621 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
622 struct ntvfs_request *req, union smb_lock *lck)
624 return NT_STATUS_ACCESS_DENIED;
628 set info on a open file
630 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
631 struct ntvfs_request *req, union smb_setfileinfo *info)
633 return NT_STATUS_ACCESS_DENIED;
637 query info on a open file
639 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
640 struct ntvfs_request *req, union smb_fileinfo *info)
642 struct ipc_private *ipriv = ntvfs->private_data;
643 struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs);
645 return NT_STATUS_INVALID_HANDLE;
647 switch (info->generic.level) {
648 case RAW_FILEINFO_GENERIC:
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;
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;
671 return ntvfs_map_qfileinfo(ntvfs, req, info);
674 return NT_STATUS_ACCESS_DENIED;
679 return filesystem info
681 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
682 struct ntvfs_request *req, union smb_fsinfo *fs)
684 return NT_STATUS_ACCESS_DENIED;
688 return print queue info
690 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
691 struct ntvfs_request *req, union smb_lpq *lpq)
693 return NT_STATUS_ACCESS_DENIED;
697 list files in a directory matching a wildcard pattern
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 *))
704 return NT_STATUS_ACCESS_DENIED;
708 continue listing files in a directory
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 *))
715 return NT_STATUS_ACCESS_DENIED;
719 end listing files in a directory
721 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
722 struct ntvfs_request *req, union smb_search_close *io)
724 return NT_STATUS_ACCESS_DENIED;
727 static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
729 NTSTATUS status = NT_STATUS_OK;
730 DATA_BLOB *blob = private_data;
732 if (out->length > blob->length) {
733 status = STATUS_BUFFER_OVERFLOW;
736 if (out->length < blob->length) {
737 blob->length = out->length;
739 memcpy(blob->data, out->data, blob->length);
740 *nwritten = blob->length;
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)
748 struct pipe_state *p;
749 struct ipc_private *ipriv = ntvfs->private_data;
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
760 SSVAL(&fnum, 0, trans->in.setup[1]);
761 fnum_key = data_blob_const(&fnum, 2);
763 p = pipe_state_find_key(ipriv, req, &fnum_key);
765 return NT_STATUS_INVALID_HANDLE;
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;
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)) {
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
787 status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
788 if (NT_STATUS_IS_ERR(status)) {
792 trans->out.setup_count = 0;
793 trans->out.setup = NULL;
794 trans->out.params = data_blob(NULL, 0);
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)
804 struct ipc_private *ipriv = ntvfs->private_data;
805 struct pipe_state *p;
808 /* the fnum is in setup[1] */
809 fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
811 p = pipe_state_find_key(ipriv, req, &fnum_key);
813 return NT_STATUS_INVALID_HANDLE;
816 if (trans->in.params.length != 2) {
817 return NT_STATUS_INVALID_PARAMETER;
819 p->ipc_state = SVAL(trans->in.params.data, 0);
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);
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)
836 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
837 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
839 if (trans->in.setup_count != 2) {
840 return NT_STATUS_INVALID_PARAMETER;
843 switch (trans->in.setup[0]) {
844 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
845 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
847 case TRANSACT_DCERPCCMD:
848 status = ipc_dcerpc_cmd(ntvfs, req, trans);
851 status = NT_STATUS_INVALID_PARAMETER;
858 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
859 struct ntvfs_request *req, union smb_ioctl *io)
861 struct pipe_state *p;
862 struct ipc_private *ipriv = ntvfs->private_data;
865 switch (io->smb2.in.function) {
866 case FSCTL_NAMED_PIPE_READ_WRITE:
870 return NT_STATUS_FS_DRIVER_REQUIRED;
873 p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs);
875 return NT_STATUS_INVALID_HANDLE;
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);
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);
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
893 status = dcesrv_output(p->dce_conn, &io->smb2.out.out, ipc_trans_dcesrv_output);
894 NT_STATUS_IS_ERR_RETURN(status);
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;
908 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
909 struct ntvfs_request *req, union smb_ioctl *io)
911 switch (io->generic.level) {
913 return ipc_ioctl_smb2(ntvfs, req, io);
915 case RAW_IOCTL_SMB2_NO_HANDLE:
916 return NT_STATUS_FS_DRIVER_REQUIRED;
919 return NT_STATUS_ACCESS_DENIED;
922 return NT_STATUS_ACCESS_DENIED;
927 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
929 NTSTATUS ntvfs_ipc_init(void)
932 struct ntvfs_ops ops;
933 NTVFS_CURRENT_CRITICAL_SIZES(vers);
937 /* fill in the name and type */
938 ops.name = "default";
939 ops.type = NTVFS_IPC;
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;
949 ops.mkdir = ipc_mkdir;
950 ops.rmdir = ipc_rmdir;
951 ops.rename = ipc_rename;
953 ops.ioctl = ipc_ioctl;
955 ops.write = ipc_write;
957 ops.flush = ipc_flush;
958 ops.close = ipc_close;
961 ops.setfileinfo = ipc_setfileinfo;
962 ops.qfileinfo = ipc_qfileinfo;
963 ops.fsinfo = ipc_fsinfo;
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;
973 /* register ourselves with the NTVFS subsystem. */
974 ret = ntvfs_register(&ops, &vers);
976 if (!NT_STATUS_IS_OK(ret)) {
977 DEBUG(0,("Failed to register IPC backend!\n"));