#include "rpc_server/dcerpc_server.h"
#include "libcli/raw/ioctl.h"
#include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
/* this is the private structure used to keep the state of an open
ipc$ connection. It needs to keep information about all open
struct ipc_private *ipriv;
const char *pipe_name;
struct ntvfs_handle *handle;
- struct dcesrv_connection *dce_conn;
uint16_t ipc_state;
+ uint16_t fmode;
+ struct tsocket_context *npipe;
} *pipe_list;
};
return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
}
+static void ipc_open_done(struct tevent_req *subreq);
+
/*
- open a file backend - used for MSRPC pipes
+ open a file - used for MSRPC pipes
*/
-static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, const char *fname,
- struct pipe_state **ps)
+static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_open *oi)
{
- struct pipe_state *p;
NTSTATUS status;
- struct dcerpc_binding *ep_description;
+ struct pipe_state *p;
struct ipc_private *ipriv = ntvfs->private_data;
struct ntvfs_handle *h;
+ struct tsocket_address *laddr;
+ struct tsocket_address *raddr;
+
+ switch (oi->generic.level) {
+ case RAW_OPEN_NTCREATEX:
+ fname = oi->ntcreatex.in.fname);
+ break;
+ case RAW_OPEN_OPENX:
+ fname = oi->openx.in.fname;
+ break;
+ case RAW_OPEN_SMB2:
+ fname = oi->smb2.in.fname;
+ break;
+ default:
+ status = NT_STATUS_NOT_SUPPORTED;
+ break;
+ }
status = ntvfs_handle_new(ntvfs, req, &h);
NT_STATUS_NOT_OK_RETURN(status);
p = talloc(h, struct pipe_state);
NT_STATUS_HAVE_NO_MEMORY(p);
- ep_description = talloc(req, struct dcerpc_binding);
- NT_STATUS_HAVE_NO_MEMORY(ep_description);
-
while (fname[0] == '\\') fname++;
- p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
- NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
+ ret = tsocket_address_npa_client_local(req, &laddr);
+ if (ret != 0) {
- p->handle = h;
- p->ipc_state = 0x5ff;
+ }
- /*
- we're all set, now ask the dcerpc server subsystem to open the
- endpoint. At this stage the pipe isn't bound, so we don't
- know what interface the user actually wants, just that they want
- one of the interfaces attached to this pipe endpoint.
- */
- ep_description->transport = NCACN_NP;
- ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
+ //Vreturn ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
+ ret = tsocket_address_npa_client_remote(req,
+ directory,
+ fname,
+ &laddr);
+ if (ret != 0) {
- /* The session info is refcount-increased in the
- * dcesrv_endpoint_search_connect() function
- */
- status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
- p,
- ep_description,
- h->session_info,
- ntvfs->ctx->event_ctx,
- ntvfs->ctx->msg_ctx,
- ntvfs->ctx->server_id,
- 0,
- &p->dce_conn);
- NT_STATUS_NOT_OK_RETURN(status);
+ }
- p->dce_conn->transport.private_data = ipriv;
- p->dce_conn->transport.report_output_data = NULL;
- p->dce_conn->transport.get_my_addr = ipc_get_my_addr;
- p->dce_conn->transport.get_peer_addr = ipc_get_peer_addr;
-
- DLIST_ADD(ipriv->pipe_list, p);
+ p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
+ NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
+ p->handle = h;
+ p->ipc_state = 0x5ff;
+ p->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
p->ipriv = ipriv;
- talloc_set_destructor(p, ipc_fd_destructor);
-
- status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
- NT_STATUS_NOT_OK_RETURN(status);
-
- *ps = p;
- return NT_STATUS_OK;
-}
-
-/*
- open a file with ntcreatex - used for MSRPC pipes
-*/
-static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, union smb_open *oi)
-{
- struct pipe_state *p;
- NTSTATUS status;
+ ret = tsocket_address_create_socket(laddr, TSOCKET_TYPE_STREAM,
+ p, &p->np_sock);
+ if (ret != 0) {
- status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
}
- ZERO_STRUCT(oi->ntcreatex.out);
- oi->ntcreatex.out.file.ntvfs= p->handle;
- oi->ntcreatex.out.ipc_state = p->ipc_state;
- oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
-
- return status;
-}
-
-/*
- open a file with openx - used for MSRPC pipes
-*/
-static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, union smb_open *oi)
-{
- struct pipe_state *p;
- NTSTATUS status;
- const char *fname = oi->openx.in.fname;
+ subreq = tsocket_connect_send(p->np_sock, p, raddr);
+ if (!subreq) {
- status = ipc_open_generic(ntvfs, req, fname, &p);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
}
+ tevent_req_set_callback(subreq, ipc_open_done, p);
- ZERO_STRUCT(oi->openx.out);
- oi->openx.out.file.ntvfs= p->handle;
- oi->openx.out.ftype = 2;
- oi->openx.out.devstate = p->ipc_state;
-
- return status;
+ /*TODO: reply async */
}
-/*
- open a file with SMB2 Create - used for MSRPC pipes
-*/
-static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, union smb_open *oi)
+static void ipc_open_done(struct tevent_req *subreq)
{
- struct pipe_state *p;
- NTSTATUS status;
- status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
- NT_STATUS_NOT_OK_RETURN(status);
+ int ret;
+ int sys_errno;
- ZERO_STRUCT(oi->smb2.out);
- oi->smb2.out.file.ntvfs = p->handle;
- oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
- oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
- oi->smb2.out.create_time = 0;
- oi->smb2.out.access_time = 0;
- oi->smb2.out.write_time = 0;
- oi->smb2.out.change_time = 0;
- oi->smb2.out.alloc_size = 4096;
- oi->smb2.out.size = 0;
- oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
- oi->smb2.out.reserved2 = 0;
+ ret = tsocket_connect_recv(subreq, &sys_errno);
+ if (ret != 0) {
- return status;
-}
+ }
-/*
- open a file - used for MSRPC pipes
-*/
-static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, union smb_open *oi)
-{
- NTSTATUS status;
+ DLIST_ADD(ipriv->pipe_list, p);
+ talloc_set_destructor(p, ipc_fd_destructor);
+ status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
+ if (!NT_STATUS_IS_OK(status)) {
+
+ }
switch (oi->generic.level) {
case RAW_OPEN_NTCREATEX:
- status = ipc_open_ntcreatex(ntvfs, req, oi);
+ ZERO_STRUCT(oi->ntcreatex.out);
+ oi->ntcreatex.out.file.ntvfs= p->handle;
+ oi->ntcreatex.out.ipc_state = p->ipc_state;
+ oi->ntcreatex.out.file_type = p->file_type;
+FILE_TYPE_MESSAGE_MODE_PIPE;
break;
case RAW_OPEN_OPENX:
- status = ipc_open_openx(ntvfs, req, oi);
+ ZERO_STRUCT(oi->openx.out);
+ oi->openx.out.file.ntvfs= p->handle;
+ oi->openx.out.ftype = p->file_type;
+ oi->openx.out.devstate = p->ipc_state;
break;
case RAW_OPEN_SMB2:
- status = ipc_open_smb2(ntvfs, req, oi);
+ ZERO_STRUCT(oi->smb2.out);
+ oi->smb2.out.file.ntvfs = p->handle;
+ oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
+ oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
+ oi->smb2.out.create_time = 0;
+ oi->smb2.out.access_time = 0;
+ oi->smb2.out.write_time = 0;
+ oi->smb2.out.change_time = 0;
+ oi->smb2.out.alloc_size = 4096;
+ oi->smb2.out.size = 0;
+ oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
+ oi->smb2.out.reserved2 = 0;
break;
default:
- status = NT_STATUS_NOT_SUPPORTED;
break;
}
- return status;
+ /*TODO: reply async */
}
/*
data.length = UINT16_MAX;
}
- if (data.length != 0) {
- status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
- if (NT_STATUS_IS_ERR(status)) {
- return status;
- }
+ subreq = tsocket_readv_queue_send(p->read_queue,
+ req);
+ if (!subreq) {
+
}
+ tevent_req_set_callback(subreq, ipc_read_done, req);
+
+ /* reply async */
+}
+
+static void ipc_read_done(struct tevent_req *subreq)
+{
+ int ret;
+ int sys_errno;
+
+ ret = tsocket_readv_queue_recv(subreq, &sys_errno);
rd->readx.out.remaining = 0;
rd->readx.out.compaction_mode = 0;
return NT_STATUS_INVALID_HANDLE;
}
- status = dcesrv_input(p->dce_conn, &data);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ subreq = tsocket_writev_queue_send(p->write_queue, req);
+ if (!subreq) {
+
+ }
+ tevent_req_set_callback(subreq, ipc_write_done, req);
+
+ /* reply async */
+}
+
+static void ipc_write_done(struct tevent_req *subreq)
+{
+ int ret;
+ int sys_errno;
+
+ ret = tsocket_writev_queue_recv(subreq, &sys_errno);
+ if (ret != 0) {
+
}
wr->writex.out.nwritten = data.length;
wr->writex.out.remaining = 0;
- return NT_STATUS_OK;
+ /* reply async */
}
/*
return NT_STATUS_INVALID_HANDLE;
}
+ if (p->num_trans || p->num_reads) {
+ return NT_STATUS_PIPE_BUSY;
+ }
+
trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
if (!trans->out.data.data) {
return NT_STATUS_NO_MEMORY;
}
- /* pass the data to the dcerpc server. Note that we don't
- expect this to fail, and things like NDR faults are not
- reported at this stage. Those sorts of errors happen in the
- dcesrv_output stage */
- status = dcesrv_input(p->dce_conn, &trans->in.data);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ p->num_trans++;
- /*
- now ask the dcerpc system for some output. This doesn't yet handle
- async calls. Again, we only expect NT_STATUS_OK. If the call fails then
- the error is encoded at the dcerpc level
- */
- status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
- if (NT_STATUS_IS_ERR(status)) {
- return status;
- }
+ subreq = tsocket_writev_queue_send(p->write_queue, req);
+ if (!subreq) {
+ }
+ tevent_req_set_callback(subreq, ipc
trans->out.setup_count = 0;
trans->out.setup = NULL;
trans->out.params = data_blob(NULL, 0);