r12608: Remove some unused #include lines.
[jelmer/samba4-debian.git] / source / ntvfs / ipc / vfs_ipc.c
index b4c41d58d35982de28d9c3ade790177851840f8e..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 "system/filesys.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
 
@@ -38,6 +39,8 @@
 struct ipc_private {
        struct idr_context *idtree_fnum;
 
+       struct dcesrv_context *dcesrv;
+
        /* a list of open pipes */
        struct pipe_state {
                struct pipe_state *next, *prev;
@@ -73,25 +76,30 @@ static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t
 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;
-       }
+       private = talloc(tcon, struct ipc_private);
+       NT_STATUS_HAVE_NO_MEMORY(private);
+
        ntvfs->private_data = private;
 
        private->pipe_list = NULL;
 
        private->idtree_fnum = idr_init(private);
-       if (private->idtree_fnum == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       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;
 }
@@ -102,13 +110,6 @@ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
                               struct smbsrv_tcon *tcon)
 {
-       struct ipc_private *private = ntvfs->private_data;
-
-       /* close any pipes that are open. Discard any unread data */
-       while (private->pipe_list) {
-               talloc_free(private->pipe_list);
-       }
-
        return NT_STATUS_OK;
 }
 
@@ -167,7 +168,6 @@ 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);
-       talloc_free(p->dce_conn);
        return 0;
 }
 
@@ -181,22 +181,25 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
 {
        struct pipe_state *p;
        NTSTATUS status;
-       struct dcerpc_binding ep_description;
-       struct auth_session_info *session_info = NULL;
+       struct dcerpc_binding *ep_description;
        struct ipc_private *private = ntvfs->private_data;
        int fnum;
+       struct stream_connection *srv_conn = req->smb_conn->connection;
 
-       p = talloc_p(req, struct pipe_state);
-       if (!p) {
-               return NT_STATUS_NO_MEMORY;
+       if (!req->session || !req->session->session_info) {
+               return NT_STATUS_ACCESS_DENIED;
        }
 
+       p = talloc(req, 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);
-       if (!p->pipe_name) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       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) {
@@ -211,24 +214,18 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
          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.transport = NCACN_NP;
-       ep_description.endpoint = 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)) {
                idr_remove(private->idtree_fnum, p->fnum);
@@ -267,6 +264,7 @@ static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
        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;
 }
@@ -353,6 +351,18 @@ static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
        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
 */
@@ -363,7 +373,7 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
        DATA_BLOB data;
        uint16_t fnum;
        struct pipe_state *p;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
        if (rd->generic.level != RAW_READ_GENERIC) {
                return ntvfs_map_read(req, rd, ntvfs);
@@ -379,11 +389,11 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
        data.length = rd->readx.in.maxcnt;
        data.data = rd->readx.out.data;
        if (data.length > UINT16_MAX) {
-               data.length = 0;
+               data.length = UINT16_MAX;
        }
 
        if (data.length != 0) {
-               status = dcesrv_output_blob(p->dce_conn, &data);
+               status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
                if (NT_STATUS_IS_ERR(status)) {
                        return status;
                }
@@ -607,6 +617,22 @@ static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
        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 ntvfs_module_context *ntvfs,
@@ -641,7 +667,7 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
          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;
        }