r12608: Remove some unused #include lines.
[jelmer/samba4-debian.git] / source / ntvfs / ipc / vfs_ipc.c
index 1ed2efba6bd62273189a422dab8d90d2812ed3b8..7eb9250eb21e921ace3da34c870a2146ddbea3ec 100644 (file)
@@ -3,7 +3,7 @@
    default IPC$ NTVFS backend
 
    Copyright (C) Andrew Tridgell 2003
-   Copyright (C) Stefan (metze) Metzmacher 2004
+   Copyright (C) Stefan (metze) Metzmacher 2004-2005
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 
 #include "includes.h"
+#include "dlinklist.h"
+#include "smb_server/smb_server.h"
+#include "ntvfs/ntvfs.h"
+#include "rpc_server/dcerpc_server.h"
+
+#define IPC_BASE_FNUM 0x400
 
 /* this is the private structure used to keep the state of an open
    ipc$ connection. It needs to keep information about all open
    pipes */
 struct ipc_private {
+       struct idr_context *idtree_fnum;
 
-       uint16_t next_fnum;
-       uint16_t num_open;
+       struct dcesrv_context *dcesrv;
 
        /* a list of open pipes */
        struct pipe_state {
                struct pipe_state *next, *prev;
-               TALLOC_CTX *mem_ctx;
+               struct ipc_private *private;
                const char *pipe_name;
                uint16_t fnum;
                struct dcesrv_connection *dce_conn;
                uint16_t ipc_state;
+               /* we need to remember the session it was opened on,
+                  as it is illegal to operate on someone elses fnum */
+               struct smbsrv_session *session;
+
+               /* we need to remember the client pid that 
+                  opened the file so SMBexit works */
+               uint16_t smbpid;
        } *pipe_list;
 
 };
 
 
-/*
-  find the next fnum available on this connection
-*/
-static uint16_t find_next_fnum(struct ipc_private *ipc)
-{
-       struct pipe_state *p;
-       uint32_t ret;
-
-       if (ipc->num_open == 0xFFFF) {
-               return 0;
-       }
-
-again:
-       ret = ipc->next_fnum++;
-
-       for (p=ipc->pipe_list; p; p=p->next) {
-               if (p->fnum == ret) {
-                       goto again;
-               }
-       }
-
-       return ret;
-}
-
-
-/*
-  shutdown a single pipe. Called on a close or disconnect
-*/
-static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
-{
-       TALLOC_CTX *mem_ctx = private->pipe_list->mem_ctx;
-       dcesrv_endpoint_disconnect(private->pipe_list->dce_conn);
-       DLIST_REMOVE(private->pipe_list, private->pipe_list);
-       talloc_destroy(mem_ctx);
-}
-
-
 /*
   find a open pipe give a file descriptor
 */
 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum)
 {
-       struct pipe_state *p;
-       
-       for (p=private->pipe_list; p; p=p->next) {
-               if (p->fnum == fnum) {
-                       return p;
-               }
-       }
-
-       return NULL;
+       return idr_find(private->idtree_fnum, fnum);
 }
 
 
 /*
   connect to a share - always works 
 */
-static NTSTATUS ipc_connect(struct smbsrv_request *req, const char *sharename, int depth)
+static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
+                           struct smbsrv_request *req, const char *sharename)
 {
+       NTSTATUS status;
        struct smbsrv_tcon *tcon = req->tcon;
        struct ipc_private *private;
 
        tcon->fs_type = talloc_strdup(tcon, "IPC");
+       NT_STATUS_HAVE_NO_MEMORY(tcon->fs_type);
+
        tcon->dev_type = talloc_strdup(tcon, "IPC");
+       NT_STATUS_HAVE_NO_MEMORY(tcon->dev_type);
 
        /* prepare the private state for this connection */
-       private = talloc_p(tcon, struct ipc_private);
-       if (!private) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       ntvfs_set_private(tcon, depth, private);
+       private = talloc(tcon, struct ipc_private);
+       NT_STATUS_HAVE_NO_MEMORY(private);
+
+       ntvfs->private_data = private;
 
        private->pipe_list = NULL;
-       private->next_fnum = 1;
-       private->num_open = 0;
+
+       private->idtree_fnum = idr_init(private);
+       NT_STATUS_HAVE_NO_MEMORY(private->idtree_fnum);
+
+       /* setup the DCERPC server subsystem */
+       status = dcesrv_init_ipc_context(private, &private->dcesrv);
+       NT_STATUS_NOT_OK_RETURN(status);
 
        return NT_STATUS_OK;
 }
@@ -130,22 +107,17 @@ static NTSTATUS ipc_connect(struct smbsrv_request *req, const char *sharename, i
 /*
   disconnect from a share
 */
-static NTSTATUS ipc_disconnect(struct smbsrv_tcon *tcon, int depth)
+static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
+                              struct smbsrv_tcon *tcon)
 {
-       struct ipc_private *private = tcon->ntvfs_private_list[depth];
-
-       /* close any pipes that are open. Discard any unread data */
-       while (private->pipe_list) {
-               pipe_shutdown(private, private->pipe_list);
-       }
-
        return NT_STATUS_OK;
 }
 
 /*
   delete a file
 */
-static NTSTATUS ipc_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
+static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req, struct smb_unlink *unl)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -154,7 +126,8 @@ static NTSTATUS ipc_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
 /*
   ioctl interface - we don't do any
 */
-static NTSTATUS ipc_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
+static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_ioctl *io)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -162,7 +135,8 @@ static NTSTATUS ipc_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
 /*
   check if a directory exists
 */
-static NTSTATUS ipc_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
+static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
+                           struct smbsrv_request *req, struct smb_chkpath *cp)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -170,7 +144,8 @@ static NTSTATUS ipc_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
 /*
   return info on a pathname
 */
-static NTSTATUS ipc_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
+                             struct smbsrv_request *req, union smb_fileinfo *info)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -178,53 +153,60 @@ static NTSTATUS ipc_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *in
 /*
   set info on a pathname
 */
-static NTSTATUS ipc_setpathinfo(struct smbsrv_request *req, union smb_setfileinfo *st)
+static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req, union smb_setfileinfo *st)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
 
 
+/*
+  destroy a open pipe structure
+*/
+static int ipc_fd_destructor(void *ptr)
+{
+       struct pipe_state *p = ptr;
+       idr_remove(p->private->idtree_fnum, p->fnum);
+       DLIST_REMOVE(p->private->pipe_list, p);
+       return 0;
+}
+
 
 /*
   open a file backend - used for MSRPC pipes
 */
-static NTSTATUS ipc_open_generic(struct smbsrv_request *req, const char *fname, 
+static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
+                                struct smbsrv_request *req, const char *fname, 
                                 struct pipe_state **ps)
 {
        struct pipe_state *p;
-       TALLOC_CTX *mem_ctx;
        NTSTATUS status;
-       struct dcesrv_ep_description ep_description;
-       struct auth_session_info *session_info = NULL;
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct dcerpc_binding *ep_description;
+       struct ipc_private *private = ntvfs->private_data;
+       int fnum;
+       struct stream_connection *srv_conn = req->smb_conn->connection;
 
-       mem_ctx = talloc_init("ipc_open '%s'", fname);
-       if (!mem_ctx) {
-               return NT_STATUS_NO_MEMORY;
+       if (!req->session || !req->session->session_info) {
+               return NT_STATUS_ACCESS_DENIED;
        }
 
-       p = talloc(mem_ctx, sizeof(struct pipe_state));
-       if (!p) {
-               talloc_destroy(mem_ctx);
-               return NT_STATUS_NO_MEMORY;
-       }
-       p->mem_ctx = mem_ctx;
+       p = talloc(req, struct pipe_state);
+       NT_STATUS_HAVE_NO_MEMORY(p);
 
-       p->pipe_name = talloc_strdup(mem_ctx, fname);
-       if (!p->pipe_name) {
-               talloc_destroy(mem_ctx);
-               return NT_STATUS_NO_MEMORY;
-       }
+       ep_description = talloc(req, struct dcerpc_binding);
+       NT_STATUS_HAVE_NO_MEMORY(ep_description);
+
+       while (fname[0] == '\\') fname++;
 
-       p->fnum = find_next_fnum(private);
-       if (p->fnum == 0) {
-               talloc_destroy(mem_ctx);
+       p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
+       NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
+
+       fnum = idr_get_new_above(private->idtree_fnum, p, IPC_BASE_FNUM, UINT16_MAX);
+       if (fnum == -1) {
                return NT_STATUS_TOO_MANY_OPENED_FILES;
        }
 
-       while (p->pipe_name[0] == '\\') {
-               p->pipe_name++;
-       }
+       p->fnum = fnum;
        p->ipc_state = 0x5ff;
 
        /*
@@ -232,50 +214,49 @@ static NTSTATUS ipc_open_generic(struct smbsrv_request *req, const char *fname,
          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.
-
-         TODO: note that we aren't passing any credentials here. We
-         will need to do that once the credentials infrastructure is
-         finalised for Samba4
        */
-
-       ep_description.type = ENDPOINT_SMB;
-       ep_description.info.smb_pipe = p->pipe_name;
-
-       /* tell the RPC layer the session_info */
-       if (req->session) {
-               /* The session info is refcount-increased in the 
-                  dcesrv_endpoint_search_connect() function */
-
-               session_info = req->session->session_info;
-       }
-
-       status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv, 
-                                               &ep_description, 
-                                               session_info,
+       ep_description->transport = NCACN_NP;
+       ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
+
+       /* The session info is refcount-increased in the 
+        * dcesrv_endpoint_search_connect() function
+        */
+       status = dcesrv_endpoint_search_connect(private->dcesrv,
+                                               p,
+                                               ep_description, 
+                                               req->session->session_info,
+                                               srv_conn,
                                                &p->dce_conn);
        if (!NT_STATUS_IS_OK(status)) {
-               talloc_destroy(mem_ctx);
+               idr_remove(private->idtree_fnum, p->fnum);
                return status;
        }
 
-       private->num_open++;
-
        DLIST_ADD(private->pipe_list, p);
 
+       p->smbpid = req->smbpid;
+       p->session = req->session;
+       p->private = private;
+
        *ps = p;
 
+       talloc_steal(private, p);
+
+       talloc_set_destructor(p, ipc_fd_destructor);
+
        return NT_STATUS_OK;
 }
 
 /*
   open a file with ntcreatex - used for MSRPC pipes
 */
-static NTSTATUS ipc_open_ntcreatex(struct smbsrv_request *req, union smb_open *oi)
+static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
+                                  struct smbsrv_request *req, union smb_open *oi)
 {
        struct pipe_state *p;
        NTSTATUS status;
 
-       status = ipc_open_generic(req, oi->ntcreatex.in.fname, &p);
+       status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -283,6 +264,7 @@ static NTSTATUS ipc_open_ntcreatex(struct smbsrv_request *req, union smb_open *o
        ZERO_STRUCT(oi->ntcreatex.out);
        oi->ntcreatex.out.fnum = p->fnum;
        oi->ntcreatex.out.ipc_state = p->ipc_state;
+       oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
 
        return status;
 }
@@ -290,19 +272,14 @@ static NTSTATUS ipc_open_ntcreatex(struct smbsrv_request *req, union smb_open *o
 /*
   open a file with openx - used for MSRPC pipes
 */
-static NTSTATUS ipc_open_openx(struct smbsrv_request *req, union smb_open *oi)
+static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
+                              struct smbsrv_request *req, union smb_open *oi)
 {
        struct pipe_state *p;
        NTSTATUS status;
        const char *fname = oi->openx.in.fname;
 
-       if (strncasecmp(fname, "PIPE\\", 5) != 0) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       fname += 4;
-
-       status = ipc_open_generic(req, fname, &p);
+       status = ipc_open_generic(ntvfs, req, fname, &p);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -318,16 +295,17 @@ static NTSTATUS ipc_open_openx(struct smbsrv_request *req, union smb_open *oi)
 /*
   open a file - used for MSRPC pipes
 */
-static NTSTATUS ipc_open(struct smbsrv_request *req, union smb_open *oi)
+static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req, union smb_open *oi)
 {
        NTSTATUS status;
 
        switch (oi->generic.level) {
        case RAW_OPEN_NTCREATEX:
-               status = ipc_open_ntcreatex(req, oi);
+               status = ipc_open_ntcreatex(ntvfs, req, oi);
                break;
        case RAW_OPEN_OPENX:
-               status = ipc_open_openx(req, oi);
+               status = ipc_open_openx(ntvfs, req, oi);
                break;
        default:
                status = NT_STATUS_NOT_SUPPORTED;
@@ -340,7 +318,8 @@ static NTSTATUS ipc_open(struct smbsrv_request *req, union smb_open *oi)
 /*
   create a directory
 */
-static NTSTATUS ipc_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
+static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_mkdir *md)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -348,7 +327,8 @@ static NTSTATUS ipc_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
 /*
   remove a directory
 */
-static NTSTATUS ipc_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
+static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, struct smb_rmdir *rd)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -356,7 +336,8 @@ static NTSTATUS ipc_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
 /*
   rename a set of files
 */
-static NTSTATUS ipc_rename(struct smbsrv_request *req, union smb_rename *ren)
+static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req, union smb_rename *ren)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -364,91 +345,87 @@ static NTSTATUS ipc_rename(struct smbsrv_request *req, union smb_rename *ren)
 /*
   copy a set of files
 */
-static NTSTATUS ipc_copy(struct smbsrv_request *req, struct smb_copy *cp)
+static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req, struct smb_copy *cp)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
 
+static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+       DATA_BLOB *blob = private_data;
+
+       if (out->length < blob->length) {
+               blob->length = out->length;
+       }
+       memcpy(blob->data, out->data, blob->length);
+       *nwritten = blob->length;
+       return NT_STATUS_OK;
+}
+
 /*
   read from a file
 */
-static NTSTATUS ipc_read(struct smbsrv_request *req, union smb_read *rd)
+static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req, union smb_read *rd)
 {
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct ipc_private *private = ntvfs->private_data;
        DATA_BLOB data;
        uint16_t fnum;
        struct pipe_state *p;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
-       switch (rd->generic.level) {
-       case RAW_READ_READ:
-               fnum = rd->read.in.fnum;
-               data.length = rd->read.in.count;
-               data.data = rd->read.out.data;
-               break;
-       case RAW_READ_READX:
-               fnum = rd->readx.in.fnum;
-               data.length = rd->readx.in.maxcnt;
-               data.data = rd->readx.out.data;
-               break;
-       default:
-               return NT_STATUS_NOT_SUPPORTED;
+       if (rd->generic.level != RAW_READ_GENERIC) {
+               return ntvfs_map_read(req, rd, ntvfs);
        }
 
+       fnum = rd->readx.in.fnum;
+
        p = pipe_state_find(private, fnum);
        if (!p) {
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       status = dcesrv_output_blob(p->dce_conn, &data);
-       if (NT_STATUS_IS_ERR(status)) {
-               return status;
+       data.length = rd->readx.in.maxcnt;
+       data.data = rd->readx.out.data;
+       if (data.length > UINT16_MAX) {
+               data.length = UINT16_MAX;
        }
 
-       switch (rd->generic.level) {
-       case RAW_READ_READ:
-               rd->read.out.nread = data.length;
-               break;
-       case RAW_READ_READX:
-               rd->readx.out.remaining = 0;
-               rd->readx.out.compaction_mode = 0;
-               rd->readx.out.nread = data.length;
-               break;
-       default:
-               return NT_STATUS_NOT_SUPPORTED;
+       if (data.length != 0) {
+               status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
+               if (NT_STATUS_IS_ERR(status)) {
+                       return status;
+               }
        }
 
+       rd->readx.out.remaining = 0;
+       rd->readx.out.compaction_mode = 0;
+       rd->readx.out.nread = data.length;
+
        return status;
 }
 
 /*
   write to a file
 */
-static NTSTATUS ipc_write(struct smbsrv_request *req, union smb_write *wr)
+static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_write *wr)
 {
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct ipc_private *private = ntvfs->private_data;
        DATA_BLOB data;
        uint16_t fnum;
        struct pipe_state *p;
        NTSTATUS status;
 
-       switch (wr->generic.level) {
-       case RAW_WRITE_WRITE:
-               fnum = wr->write.in.fnum;
-               data.data = wr->write.in.data;
-               data.length = wr->write.in.count;
-               break;
-
-       case RAW_WRITE_WRITEX:
-               fnum = wr->writex.in.fnum;
-               data.data = wr->writex.in.data;
-               data.length = wr->writex.in.count;
-               break;
-
-       default:
-               return NT_STATUS_NOT_SUPPORTED;
+       if (wr->generic.level != RAW_WRITE_GENERIC) {
+               return ntvfs_map_write(req, wr, ntvfs);
        }
 
+       fnum = wr->writex.in.fnum;
+       data.data = discard_const_p(void, wr->writex.in.data);
+       data.length = wr->writex.in.count;
+
        p = pipe_state_find(private, fnum);
        if (!p) {
                return NT_STATUS_INVALID_HANDLE;
@@ -459,17 +436,8 @@ static NTSTATUS ipc_write(struct smbsrv_request *req, union smb_write *wr)
                return status;
        }
 
-       switch (wr->generic.level) {
-       case RAW_WRITE_WRITE:
-               wr->write.out.nwritten = data.length;
-               break;
-       case RAW_WRITE_WRITEX:
-               wr->writex.out.nwritten = data.length;
-               wr->writex.out.remaining = 0;
-               break;
-       default:
-               return NT_STATUS_NOT_SUPPORTED;
-       }
+       wr->writex.out.nwritten = data.length;
+       wr->writex.out.remaining = 0;
 
        return NT_STATUS_OK;
 }
@@ -477,7 +445,8 @@ static NTSTATUS ipc_write(struct smbsrv_request *req, union smb_write *wr)
 /*
   seek in a file
 */
-static NTSTATUS ipc_seek(struct smbsrv_request *req, struct smb_seek *io)
+static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req, struct smb_seek *io)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -485,7 +454,8 @@ static NTSTATUS ipc_seek(struct smbsrv_request *req, struct smb_seek *io)
 /*
   flush a file
 */
-static NTSTATUS ipc_flush(struct smbsrv_request *req, struct smb_flush *io)
+static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, struct smb_flush *io)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -493,13 +463,14 @@ static NTSTATUS ipc_flush(struct smbsrv_request *req, struct smb_flush *io)
 /*
   close a file
 */
-static NTSTATUS ipc_close(struct smbsrv_request *req, union smb_close *io)
+static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_close *io)
 {
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct ipc_private *private = ntvfs->private_data;
        struct pipe_state *p;
 
        if (io->generic.level != RAW_CLOSE_CLOSE) {
-               return NT_STATUS_ACCESS_DENIED;
+               return ntvfs_map_close(req, io, ntvfs);
        }
 
        p = pipe_state_find(private, io->close.in.fnum);
@@ -507,24 +478,73 @@ static NTSTATUS ipc_close(struct smbsrv_request *req, union smb_close *io)
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       pipe_shutdown(private, p);
-       private->num_open--;
+       talloc_free(p);
 
        return NT_STATUS_OK;
 }
 
 /*
-  exit - closing files?
+  exit - closing files
 */
-static NTSTATUS ipc_exit(struct smbsrv_request *req)
+static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req)
 {
-       return NT_STATUS_ACCESS_DENIED;
+       struct ipc_private *private = ntvfs->private_data;
+       struct pipe_state *p, *next;
+       
+       for (p=private->pipe_list; p; p=next) {
+               next = p->next;
+               if (p->smbpid == req->smbpid) {
+                       talloc_free(p);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  logoff - closing files open by the user
+*/
+static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req)
+{
+       struct ipc_private *private = ntvfs->private_data;
+       struct pipe_state *p, *next;
+       
+       for (p=private->pipe_list; p; p=next) {
+               next = p->next;
+               if (p->session == req->session) {
+                       talloc_free(p);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  setup for an async call
+*/
+static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req,
+                               void *private)
+{
+       return NT_STATUS_OK;
+}
+
+/*
+  cancel an async call
+*/
+static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req)
+{
+       return NT_STATUS_UNSUCCESSFUL;
 }
 
 /*
   lock a byte range
 */
-static NTSTATUS ipc_lock(struct smbsrv_request *req, union smb_lock *lck)
+static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req, union smb_lock *lck)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -532,7 +552,8 @@ static NTSTATUS ipc_lock(struct smbsrv_request *req, union smb_lock *lck)
 /*
   set info on a open file
 */
-static NTSTATUS ipc_setfileinfo(struct smbsrv_request *req, union smb_setfileinfo *info)
+static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req, union smb_setfileinfo *info)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -540,7 +561,8 @@ static NTSTATUS ipc_setfileinfo(struct smbsrv_request *req, union smb_setfileinf
 /*
   query info on a open file
 */
-static NTSTATUS ipc_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
+                             struct smbsrv_request *req, union smb_fileinfo *info)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -549,7 +571,8 @@ static NTSTATUS ipc_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *in
 /*
   return filesystem info
 */
-static NTSTATUS ipc_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
+static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req, union smb_fsinfo *fs)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -557,7 +580,8 @@ static NTSTATUS ipc_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
 /*
   return print queue info
 */
-static NTSTATUS ipc_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
+static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
+                       struct smbsrv_request *req, union smb_lpq *lpq)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
@@ -565,7 +589,8 @@ static NTSTATUS ipc_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
 /* 
    list files in a directory matching a wildcard pattern
 */
-NTSTATUS ipc_search_first(struct smbsrv_request *req, union smb_search_first *io,
+static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_search_first *io,
                          void *search_private, 
                          BOOL (*callback)(void *, union smb_search_data *))
 {
@@ -575,7 +600,8 @@ NTSTATUS ipc_search_first(struct smbsrv_request *req, union smb_search_first *io
 /* 
    continue listing files in a directory 
 */
-NTSTATUS ipc_search_next(struct smbsrv_request *req, union smb_search_next *io,
+static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
+                        struct smbsrv_request *req, union smb_search_next *io,
                         void *search_private, 
                         BOOL (*callback)(void *, union smb_search_data *))
 {
@@ -585,17 +611,35 @@ NTSTATUS ipc_search_next(struct smbsrv_request *req, union smb_search_next *io,
 /* 
    end listing files in a directory 
 */
-NTSTATUS ipc_search_close(struct smbsrv_request *req, union smb_search_close *io)
+static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, union smb_search_close *io)
 {
        return NT_STATUS_ACCESS_DENIED;
 }
 
+static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       DATA_BLOB *blob = private_data;
+
+       if (out->length > blob->length) {
+               status = STATUS_BUFFER_OVERFLOW;
+       }
+
+       if (out->length < blob->length) {
+               blob->length = out->length;
+       }
+       memcpy(blob->data, out->data, blob->length);
+       *nwritten = blob->length;
+       return status;
+}
 
 /* SMBtrans - handle a DCERPC command */
-static NTSTATUS ipc_dcerpc_cmd(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
+                              struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        struct pipe_state *p;
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct ipc_private *private = ntvfs->private_data;
        NTSTATUS status;
 
        /* the fnum is in setup[1] */
@@ -623,7 +667,7 @@ static NTSTATUS ipc_dcerpc_cmd(struct smbsrv_request *req, struct smb_trans2 *tr
          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_blob(p->dce_conn, &trans->out.data);
+       status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
        if (NT_STATUS_IS_ERR(status)) {
                return status;
        }
@@ -637,9 +681,10 @@ static NTSTATUS ipc_dcerpc_cmd(struct smbsrv_request *req, struct smb_trans2 *tr
 
 
 /* SMBtrans - set named pipe state */
-static NTSTATUS ipc_set_nm_pipe_state(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req, struct smb_trans2 *trans)
 {
-       NTVFS_GET_PRIVATE(ipc_private, private, req);
+       struct ipc_private *private = ntvfs->private_data;
        struct pipe_state *p;
 
        /* the fnum is in setup[1] */
@@ -663,7 +708,8 @@ static NTSTATUS ipc_set_nm_pipe_state(struct smbsrv_request *req, struct smb_tra
 
 
 /* SMBtrans - used to provide access to SMB pipes */
-static NTSTATUS ipc_trans(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        NTSTATUS status;
 
@@ -676,10 +722,10 @@ static NTSTATUS ipc_trans(struct smbsrv_request *req, struct smb_trans2 *trans)
 
        switch (trans->in.setup[0]) {
        case TRANSACT_SETNAMEDPIPEHANDLESTATE:
-               status = ipc_set_nm_pipe_state(req, trans);
+               status = ipc_set_nm_pipe_state(ntvfs, req, trans);
                break;
        case TRANSACT_DCERPCCMD:
-               status = ipc_dcerpc_cmd(req, trans);
+               status = ipc_dcerpc_cmd(ntvfs, req, trans);
                break;
        default:
                status = NT_STATUS_INVALID_PARAMETER;
@@ -712,7 +758,7 @@ NTSTATUS ntvfs_ipc_init(void)
        ops.chkpath = ipc_chkpath;
        ops.qpathinfo = ipc_qpathinfo;
        ops.setpathinfo = ipc_setpathinfo;
-       ops.open = ipc_open;
+       ops.openfile = ipc_open;
        ops.mkdir = ipc_mkdir;
        ops.rmdir = ipc_rmdir;
        ops.rename = ipc_rename;
@@ -733,9 +779,12 @@ NTSTATUS ntvfs_ipc_init(void)
        ops.search_next = ipc_search_next;
        ops.search_close = ipc_search_close;
        ops.trans = ipc_trans;
+       ops.logoff = ipc_logoff;
+       ops.async_setup = ipc_async_setup;
+       ops.cancel = ipc_cancel;
 
        /* register ourselves with the NTVFS subsystem. */
-       ret = register_backend("ntvfs", &ops);
+       ret = ntvfs_register(&ops);
 
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(0,("Failed to register IPC backend!\n"));