Revert "Revert "s3-printing: update parent smbd pcap cache""
[Samba.git] / source4 / ntvfs / ipc / vfs_ipc.c
blob2f05a86dfab882e90e43f626d5277b0197465d7c
1 /*
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
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"
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;
42 struct dcesrv_context *dcesrv;
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;
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)
61 struct pipe_state *s;
62 void *p;
64 p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs);
65 if (!p) return NULL;
67 s = talloc_get_type(p, struct pipe_state);
68 if (!s) return NULL;
70 return s;
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);
81 if (!h) return NULL;
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, const char *sharename)
93 NTSTATUS status;
94 struct ipc_private *ipriv;
96 ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
97 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
99 ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
100 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
102 /* prepare the private state for this connection */
103 ipriv = talloc(ntvfs, struct ipc_private);
104 NT_STATUS_HAVE_NO_MEMORY(ipriv);
106 ntvfs->private_data = ipriv;
108 ipriv->ntvfs = ntvfs;
109 ipriv->pipe_list = NULL;
111 /* setup the DCERPC server subsystem */
112 status = dcesrv_init_ipc_context(ipriv, ntvfs->ctx->lp_ctx, &ipriv->dcesrv);
113 NT_STATUS_NOT_OK_RETURN(status);
115 return NT_STATUS_OK;
119 disconnect from a share
121 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
123 return NT_STATUS_OK;
127 delete a file
129 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
130 struct ntvfs_request *req,
131 union smb_unlink *unl)
133 return NT_STATUS_ACCESS_DENIED;
137 check if a directory exists
139 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
140 struct ntvfs_request *req,
141 union smb_chkpath *cp)
143 return NT_STATUS_ACCESS_DENIED;
147 return info on a pathname
149 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
150 struct ntvfs_request *req, union smb_fileinfo *info)
152 switch (info->generic.level) {
153 case RAW_FILEINFO_GENERIC:
154 return NT_STATUS_INVALID_DEVICE_REQUEST;
155 case RAW_FILEINFO_GETATTR:
156 return NT_STATUS_ACCESS_DENIED;
157 default:
158 return ntvfs_map_qpathinfo(ntvfs, req, info);
163 set info on a pathname
165 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
166 struct ntvfs_request *req, union smb_setfileinfo *st)
168 return NT_STATUS_ACCESS_DENIED;
173 destroy a open pipe structure
175 static int ipc_fd_destructor(struct pipe_state *p)
177 DLIST_REMOVE(p->ipriv->pipe_list, p);
178 ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs);
179 return 0;
182 static struct socket_address *ipc_get_my_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
184 struct ipc_private *ipriv = dce_conn->transport.private_data;
186 return ntvfs_get_my_addr(ipriv->ntvfs, mem_ctx);
189 static struct socket_address *ipc_get_peer_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
191 struct ipc_private *ipriv = dce_conn->transport.private_data;
193 return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
197 open a file backend - used for MSRPC pipes
199 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
200 struct ntvfs_request *req, const char *fname,
201 struct pipe_state **ps)
203 struct pipe_state *p;
204 NTSTATUS status;
205 struct dcerpc_binding *ep_description;
206 struct ipc_private *ipriv = ntvfs->private_data;
207 struct ntvfs_handle *h;
209 status = ntvfs_handle_new(ntvfs, req, &h);
210 NT_STATUS_NOT_OK_RETURN(status);
212 p = talloc(h, struct pipe_state);
213 NT_STATUS_HAVE_NO_MEMORY(p);
215 ep_description = talloc(req, struct dcerpc_binding);
216 NT_STATUS_HAVE_NO_MEMORY(ep_description);
218 while (fname[0] == '\\') fname++;
220 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
221 NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
223 p->handle = h;
224 p->ipc_state = 0x5ff;
227 we're all set, now ask the dcerpc server subsystem to open the
228 endpoint. At this stage the pipe isn't bound, so we don't
229 know what interface the user actually wants, just that they want
230 one of the interfaces attached to this pipe endpoint.
232 ep_description->transport = NCACN_NP;
233 ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
235 /* The session info is refcount-increased in the
236 * dcesrv_endpoint_search_connect() function
238 status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
240 ep_description,
241 h->session_info,
242 ntvfs->ctx->event_ctx,
243 ntvfs->ctx->msg_ctx,
244 ntvfs->ctx->server_id,
246 &p->dce_conn);
247 NT_STATUS_NOT_OK_RETURN(status);
249 p->dce_conn->transport.private_data = ipriv;
250 p->dce_conn->transport.report_output_data = NULL;
251 p->dce_conn->transport.get_my_addr = ipc_get_my_addr;
252 p->dce_conn->transport.get_peer_addr = ipc_get_peer_addr;
254 DLIST_ADD(ipriv->pipe_list, p);
256 p->ipriv = ipriv;
258 talloc_set_destructor(p, ipc_fd_destructor);
260 status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
261 NT_STATUS_NOT_OK_RETURN(status);
263 *ps = p;
264 return NT_STATUS_OK;
268 open a file with ntcreatex - used for MSRPC pipes
270 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
271 struct ntvfs_request *req, union smb_open *oi)
273 struct pipe_state *p;
274 NTSTATUS status;
276 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
277 if (!NT_STATUS_IS_OK(status)) {
278 return status;
281 ZERO_STRUCT(oi->ntcreatex.out);
282 oi->ntcreatex.out.file.ntvfs= p->handle;
283 oi->ntcreatex.out.ipc_state = p->ipc_state;
284 oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
286 return status;
290 open a file with openx - used for MSRPC pipes
292 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
293 struct ntvfs_request *req, union smb_open *oi)
295 struct pipe_state *p;
296 NTSTATUS status;
297 const char *fname = oi->openx.in.fname;
299 status = ipc_open_generic(ntvfs, req, fname, &p);
300 if (!NT_STATUS_IS_OK(status)) {
301 return status;
304 ZERO_STRUCT(oi->openx.out);
305 oi->openx.out.file.ntvfs= p->handle;
306 oi->openx.out.ftype = 2;
307 oi->openx.out.devstate = p->ipc_state;
309 return status;
313 open a file with SMB2 Create - used for MSRPC pipes
315 static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
316 struct ntvfs_request *req, union smb_open *oi)
318 struct pipe_state *p;
319 NTSTATUS status;
321 status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
322 NT_STATUS_NOT_OK_RETURN(status);
324 ZERO_STRUCT(oi->smb2.out);
325 oi->smb2.out.file.ntvfs = p->handle;
326 oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
327 oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
328 oi->smb2.out.create_time = 0;
329 oi->smb2.out.access_time = 0;
330 oi->smb2.out.write_time = 0;
331 oi->smb2.out.change_time = 0;
332 oi->smb2.out.alloc_size = 4096;
333 oi->smb2.out.size = 0;
334 oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
335 oi->smb2.out.reserved2 = 0;
337 return status;
341 open a file - used for MSRPC pipes
343 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
344 struct ntvfs_request *req, union smb_open *oi)
346 NTSTATUS status;
348 switch (oi->generic.level) {
349 case RAW_OPEN_NTCREATEX:
350 status = ipc_open_ntcreatex(ntvfs, req, oi);
351 break;
352 case RAW_OPEN_OPENX:
353 status = ipc_open_openx(ntvfs, req, oi);
354 break;
355 case RAW_OPEN_SMB2:
356 status = ipc_open_smb2(ntvfs, req, oi);
357 break;
358 default:
359 status = NT_STATUS_NOT_SUPPORTED;
360 break;
363 return status;
367 create a directory
369 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
370 struct ntvfs_request *req, union smb_mkdir *md)
372 return NT_STATUS_ACCESS_DENIED;
376 remove a directory
378 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
379 struct ntvfs_request *req, struct smb_rmdir *rd)
381 return NT_STATUS_ACCESS_DENIED;
385 rename a set of files
387 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
388 struct ntvfs_request *req, union smb_rename *ren)
390 return NT_STATUS_ACCESS_DENIED;
394 copy a set of files
396 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
397 struct ntvfs_request *req, struct smb_copy *cp)
399 return NT_STATUS_ACCESS_DENIED;
402 static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
404 DATA_BLOB *blob = private_data;
406 if (out->length < blob->length) {
407 blob->length = out->length;
409 memcpy(blob->data, out->data, blob->length);
410 *nwritten = blob->length;
411 return NT_STATUS_OK;
415 read from a file
417 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
418 struct ntvfs_request *req, union smb_read *rd)
420 struct ipc_private *ipriv = ntvfs->private_data;
421 DATA_BLOB data;
422 struct pipe_state *p;
423 NTSTATUS status = NT_STATUS_OK;
425 if (rd->generic.level != RAW_READ_GENERIC) {
426 return ntvfs_map_read(ntvfs, req, rd);
429 p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs);
430 if (!p) {
431 return NT_STATUS_INVALID_HANDLE;
434 data.length = rd->readx.in.maxcnt;
435 data.data = rd->readx.out.data;
436 if (data.length > UINT16_MAX) {
437 data.length = UINT16_MAX;
440 if (data.length != 0) {
441 status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
442 if (NT_STATUS_IS_ERR(status)) {
443 return status;
447 rd->readx.out.remaining = 0;
448 rd->readx.out.compaction_mode = 0;
449 rd->readx.out.nread = data.length;
451 return status;
455 write to a file
457 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
458 struct ntvfs_request *req, union smb_write *wr)
460 struct ipc_private *ipriv = ntvfs->private_data;
461 DATA_BLOB data;
462 struct pipe_state *p;
463 NTSTATUS status;
465 if (wr->generic.level != RAW_WRITE_GENERIC) {
466 return ntvfs_map_write(ntvfs, req, wr);
469 data.data = discard_const_p(void, wr->writex.in.data);
470 data.length = wr->writex.in.count;
472 p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs);
473 if (!p) {
474 return NT_STATUS_INVALID_HANDLE;
477 status = dcesrv_input(p->dce_conn, &data);
478 if (!NT_STATUS_IS_OK(status)) {
479 return status;
482 wr->writex.out.nwritten = data.length;
483 wr->writex.out.remaining = 0;
485 return NT_STATUS_OK;
489 seek in a file
491 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
492 struct ntvfs_request *req,
493 union smb_seek *io)
495 return NT_STATUS_ACCESS_DENIED;
499 flush a file
501 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
502 struct ntvfs_request *req,
503 union smb_flush *io)
505 return NT_STATUS_ACCESS_DENIED;
509 close a file
511 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
512 struct ntvfs_request *req, union smb_close *io)
514 struct ipc_private *ipriv = ntvfs->private_data;
515 struct pipe_state *p;
517 if (io->generic.level != RAW_CLOSE_CLOSE) {
518 return ntvfs_map_close(ntvfs, req, io);
521 p = pipe_state_find(ipriv, io->close.in.file.ntvfs);
522 if (!p) {
523 return NT_STATUS_INVALID_HANDLE;
526 talloc_free(p);
528 return NT_STATUS_OK;
532 exit - closing files
534 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
535 struct ntvfs_request *req)
537 struct ipc_private *ipriv = ntvfs->private_data;
538 struct pipe_state *p, *next;
540 for (p=ipriv->pipe_list; p; p=next) {
541 next = p->next;
542 if (p->handle->session_info == req->session_info &&
543 p->handle->smbpid == req->smbpid) {
544 talloc_free(p);
548 return NT_STATUS_OK;
552 logoff - closing files open by the user
554 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
555 struct ntvfs_request *req)
557 struct ipc_private *ipriv = ntvfs->private_data;
558 struct pipe_state *p, *next;
560 for (p=ipriv->pipe_list; p; p=next) {
561 next = p->next;
562 if (p->handle->session_info == req->session_info) {
563 talloc_free(p);
567 return NT_STATUS_OK;
571 setup for an async call
573 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
574 struct ntvfs_request *req,
575 void *private_data)
577 return NT_STATUS_OK;
581 cancel an async call
583 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
584 struct ntvfs_request *req)
586 return NT_STATUS_UNSUCCESSFUL;
590 lock a byte range
592 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
593 struct ntvfs_request *req, union smb_lock *lck)
595 return NT_STATUS_ACCESS_DENIED;
599 set info on a open file
601 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
602 struct ntvfs_request *req, union smb_setfileinfo *info)
604 return NT_STATUS_ACCESS_DENIED;
608 query info on a open file
610 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
611 struct ntvfs_request *req, union smb_fileinfo *info)
613 struct ipc_private *ipriv = ntvfs->private_data;
614 struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs);
615 if (!p) {
616 return NT_STATUS_INVALID_HANDLE;
618 switch (info->generic.level) {
619 case RAW_FILEINFO_GENERIC:
621 ZERO_STRUCT(info->generic.out);
622 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL;
623 info->generic.out.fname.s = strrchr(p->pipe_name, '\\');
624 info->generic.out.alloc_size = 4096;
625 info->generic.out.nlink = 1;
626 /* What the heck? Match Win2k3: IPC$ pipes are delete pending */
627 info->generic.out.delete_pending = 1;
628 return NT_STATUS_OK;
630 case RAW_FILEINFO_ALT_NAME_INFO:
631 case RAW_FILEINFO_ALT_NAME_INFORMATION:
632 case RAW_FILEINFO_STREAM_INFO:
633 case RAW_FILEINFO_STREAM_INFORMATION:
634 case RAW_FILEINFO_COMPRESSION_INFO:
635 case RAW_FILEINFO_COMPRESSION_INFORMATION:
636 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
637 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
638 return NT_STATUS_INVALID_PARAMETER;
639 case RAW_FILEINFO_ALL_EAS:
640 return NT_STATUS_ACCESS_DENIED;
641 default:
642 return ntvfs_map_qfileinfo(ntvfs, req, info);
645 return NT_STATUS_ACCESS_DENIED;
650 return filesystem info
652 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
653 struct ntvfs_request *req, union smb_fsinfo *fs)
655 return NT_STATUS_ACCESS_DENIED;
659 return print queue info
661 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
662 struct ntvfs_request *req, union smb_lpq *lpq)
664 return NT_STATUS_ACCESS_DENIED;
668 list files in a directory matching a wildcard pattern
670 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
671 struct ntvfs_request *req, union smb_search_first *io,
672 void *search_private,
673 bool (*callback)(void *, const union smb_search_data *))
675 return NT_STATUS_ACCESS_DENIED;
679 continue listing files in a directory
681 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
682 struct ntvfs_request *req, union smb_search_next *io,
683 void *search_private,
684 bool (*callback)(void *, const union smb_search_data *))
686 return NT_STATUS_ACCESS_DENIED;
690 end listing files in a directory
692 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
693 struct ntvfs_request *req, union smb_search_close *io)
695 return NT_STATUS_ACCESS_DENIED;
698 static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
700 NTSTATUS status = NT_STATUS_OK;
701 DATA_BLOB *blob = private_data;
703 if (out->length > blob->length) {
704 status = STATUS_BUFFER_OVERFLOW;
707 if (out->length < blob->length) {
708 blob->length = out->length;
710 memcpy(blob->data, out->data, blob->length);
711 *nwritten = blob->length;
712 return status;
715 /* SMBtrans - handle a DCERPC command */
716 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
717 struct ntvfs_request *req, struct smb_trans2 *trans)
719 struct pipe_state *p;
720 struct ipc_private *ipriv = ntvfs->private_data;
721 NTSTATUS status;
722 DATA_BLOB fnum_key;
723 uint16_t fnum;
726 * the fnum is in setup[1], a 16 bit value
727 * the setup[*] values are already in host byteorder
728 * but ntvfs_handle_search_by_wire_key() expects
729 * network byteorder
731 SSVAL(&fnum, 0, trans->in.setup[1]);
732 fnum_key = data_blob_const(&fnum, 2);
734 p = pipe_state_find_key(ipriv, req, &fnum_key);
735 if (!p) {
736 return NT_STATUS_INVALID_HANDLE;
739 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
740 if (!trans->out.data.data) {
741 return NT_STATUS_NO_MEMORY;
744 /* pass the data to the dcerpc server. Note that we don't
745 expect this to fail, and things like NDR faults are not
746 reported at this stage. Those sorts of errors happen in the
747 dcesrv_output stage */
748 status = dcesrv_input(p->dce_conn, &trans->in.data);
749 if (!NT_STATUS_IS_OK(status)) {
750 return status;
754 now ask the dcerpc system for some output. This doesn't yet handle
755 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
756 the error is encoded at the dcerpc level
758 status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
759 if (NT_STATUS_IS_ERR(status)) {
760 return status;
763 trans->out.setup_count = 0;
764 trans->out.setup = NULL;
765 trans->out.params = data_blob(NULL, 0);
767 return status;
771 /* SMBtrans - set named pipe state */
772 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
773 struct ntvfs_request *req, struct smb_trans2 *trans)
775 struct ipc_private *ipriv = ntvfs->private_data;
776 struct pipe_state *p;
777 DATA_BLOB fnum_key;
779 /* the fnum is in setup[1] */
780 fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
782 p = pipe_state_find_key(ipriv, req, &fnum_key);
783 if (!p) {
784 return NT_STATUS_INVALID_HANDLE;
787 if (trans->in.params.length != 2) {
788 return NT_STATUS_INVALID_PARAMETER;
790 p->ipc_state = SVAL(trans->in.params.data, 0);
792 trans->out.setup_count = 0;
793 trans->out.setup = NULL;
794 trans->out.params = data_blob(NULL, 0);
795 trans->out.data = data_blob(NULL, 0);
797 return NT_STATUS_OK;
801 /* SMBtrans - used to provide access to SMB pipes */
802 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
803 struct ntvfs_request *req, struct smb_trans2 *trans)
805 NTSTATUS status;
807 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
808 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
810 if (trans->in.setup_count != 2) {
811 return NT_STATUS_INVALID_PARAMETER;
814 switch (trans->in.setup[0]) {
815 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
816 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
817 break;
818 case TRANSACT_DCERPCCMD:
819 status = ipc_dcerpc_cmd(ntvfs, req, trans);
820 break;
821 default:
822 status = NT_STATUS_INVALID_PARAMETER;
823 break;
826 return status;
829 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
830 struct ntvfs_request *req, union smb_ioctl *io)
832 struct pipe_state *p;
833 struct ipc_private *ipriv = ntvfs->private_data;
834 NTSTATUS status;
836 switch (io->smb2.in.function) {
837 case FSCTL_NAMED_PIPE_READ_WRITE:
838 break;
840 default:
841 return NT_STATUS_FS_DRIVER_REQUIRED;
844 p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs);
845 if (!p) {
846 return NT_STATUS_INVALID_HANDLE;
849 io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_response_size);
850 NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data);
852 /* pass the data to the dcerpc server. Note that we don't
853 expect this to fail, and things like NDR faults are not
854 reported at this stage. Those sorts of errors happen in the
855 dcesrv_output stage */
856 status = dcesrv_input(p->dce_conn, &io->smb2.in.out);
857 NT_STATUS_NOT_OK_RETURN(status);
860 now ask the dcerpc system for some output. This doesn't yet handle
861 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
862 the error is encoded at the dcerpc level
864 status = dcesrv_output(p->dce_conn, &io->smb2.out.out, ipc_trans_dcesrv_output);
865 NT_STATUS_IS_ERR_RETURN(status);
867 io->smb2.out._pad = 0;
868 io->smb2.out.function = io->smb2.in.function;
869 io->smb2.out.unknown2 = 0;
870 io->smb2.out.unknown3 = 0;
871 io->smb2.out.in = io->smb2.in.out;
873 return status;
877 ioctl interface
879 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
880 struct ntvfs_request *req, union smb_ioctl *io)
882 switch (io->generic.level) {
883 case RAW_IOCTL_SMB2:
884 return ipc_ioctl_smb2(ntvfs, req, io);
886 case RAW_IOCTL_SMB2_NO_HANDLE:
887 return NT_STATUS_FS_DRIVER_REQUIRED;
889 default:
890 return NT_STATUS_ACCESS_DENIED;
893 return NT_STATUS_ACCESS_DENIED;
898 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
900 NTSTATUS ntvfs_ipc_init(void)
902 NTSTATUS ret;
903 struct ntvfs_ops ops;
904 NTVFS_CURRENT_CRITICAL_SIZES(vers);
906 ZERO_STRUCT(ops);
908 /* fill in the name and type */
909 ops.name = "default";
910 ops.type = NTVFS_IPC;
912 /* fill in all the operations */
913 ops.connect = ipc_connect;
914 ops.disconnect = ipc_disconnect;
915 ops.unlink = ipc_unlink;
916 ops.chkpath = ipc_chkpath;
917 ops.qpathinfo = ipc_qpathinfo;
918 ops.setpathinfo = ipc_setpathinfo;
919 ops.open = ipc_open;
920 ops.mkdir = ipc_mkdir;
921 ops.rmdir = ipc_rmdir;
922 ops.rename = ipc_rename;
923 ops.copy = ipc_copy;
924 ops.ioctl = ipc_ioctl;
925 ops.read = ipc_read;
926 ops.write = ipc_write;
927 ops.seek = ipc_seek;
928 ops.flush = ipc_flush;
929 ops.close = ipc_close;
930 ops.exit = ipc_exit;
931 ops.lock = ipc_lock;
932 ops.setfileinfo = ipc_setfileinfo;
933 ops.qfileinfo = ipc_qfileinfo;
934 ops.fsinfo = ipc_fsinfo;
935 ops.lpq = ipc_lpq;
936 ops.search_first = ipc_search_first;
937 ops.search_next = ipc_search_next;
938 ops.search_close = ipc_search_close;
939 ops.trans = ipc_trans;
940 ops.logoff = ipc_logoff;
941 ops.async_setup = ipc_async_setup;
942 ops.cancel = ipc_cancel;
944 /* register ourselves with the NTVFS subsystem. */
945 ret = ntvfs_register(&ops, &vers);
947 if (!NT_STATUS_IS_OK(ret)) {
948 DEBUG(0,("Failed to register IPC backend!\n"));
949 return ret;
952 return ret;