[CIFS] CIFS support for named pipes (part 1)
authorSteve French <sfrench@us.ibm.com>
Fri, 28 Sep 2007 22:28:55 +0000 (22:28 +0000)
committerSteve French <sfrench@us.ibm.com>
Fri, 28 Sep 2007 22:28:55 +0000 (22:28 +0000)
This allows cifs to mount to ipc shares (IPC$)
which will allow user space applications to
layer over authenticated cifs connections
(useful for Wine and others that would want
to put DCE/RPC over CIFS or run CIFS named
pipes)

Acked-by: Rob Shearman <rob@codeweavers.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/misc.c

index bb468de4f4745d2be45931a5319714913ef563dc..f55be8efa26d45dbc62de62b72244ff95fcf2946 100644 (file)
@@ -291,6 +291,7 @@ struct cifsTconInfo {
        FILE_SYSTEM_DEVICE_INFO fsDevInfo;
        FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
        FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+       unsigned ipc:1;         /* set if connection to IPC$ eg for RPC/PIPES */
        unsigned retry:1;
        unsigned nocase:1;
        unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
@@ -341,6 +342,7 @@ struct cifsFileInfo {
        struct list_head llist; /* list of byte range locks we have. */
        unsigned closePend:1;   /* file is marked to close */
        unsigned invalidHandle:1;  /* file closed via session abend */
+       unsigned messageMode:1    /* for pipes: is message or byte mode */
        atomic_t wrtPending;   /* handle in use - defer close */
        struct semaphore fh_sem; /* prevents reopen race after dead ses*/
        char *search_resume_name; /* BB removeme BB */
index e43cb880f54ab12ffc26f56fecd8f434e458fcac..21cac15ed9a720fe607d661e5ef26fb42ca28019 100644 (file)
@@ -2186,8 +2186,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                tcon->ses = pSesInfo;
 
                /* do not care if following two calls succeed - informational */
-               CIFSSMBQFSDeviceInfo(xid, tcon);
-               CIFSSMBQFSAttributeInfo(xid, tcon);
+               if (!tcon->ipc) {
+                       CIFSSMBQFSDeviceInfo(xid, tcon);
+                       CIFSSMBQFSAttributeInfo(xid, tcon);
+               }
 
                /* tell server which Unix caps we support */
                if (tcon->ses->capabilities & CAP_UNIX)
@@ -3385,6 +3387,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                bcc_ptr = pByteArea(smb_buffer_response);
                length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
                /* skip service field (NB: this field is always ASCII) */
+               if (length == 3) {
+                       if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
+                           (bcc_ptr[2] == 'C')) {
+                               cFYI(1, ("IPC connection"));
+                               tcon->ipc = 1;
+                       }
+               } else if (length == 2) {
+                       if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
+                               /* the most common case */
+                               cFYI(1, ("disk share connection"));
+                       }
+               }
                bcc_ptr += length + 1;
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
index db5287abc30fc59e40cfebaa48e0abf0f486de3e..99321ab439d26e49930a78f7f007488ce13b993c 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   vfs operations that deal with dentries
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Copyright (C) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
index 552d68b9d6f4924db1a0d20e226650145de2d2df..ece17ca00d0847270bdf3af2e87f1a72c3b96c41 100644 (file)
@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                inode->i_mode = le64_to_cpu(findData.Permissions);
                /* since we set the inode type below we need to mask off
                   to avoid strange results if bits set above */
-                       inode->i_mode &= ~S_IFMT;
+               inode->i_mode &= ~S_IFMT;
                if (type == UNIX_FILE) {
                        inode->i_mode |= S_IFREG;
                } else if (type == UNIX_SYMLINK) {
@@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
        return rc;
 }
 
+static const struct inode_operations cifs_ipc_inode_ops = {
+       .lookup = cifs_lookup,
+};
+
 /* gets root inode */
 void cifs_read_inode(struct inode *inode)
 {
-       int xid;
+       int xid, rc;
        struct cifs_sb_info *cifs_sb;
 
        cifs_sb = CIFS_SB(inode->i_sb);
        xid = GetXid();
 
        if (cifs_sb->tcon->unix_ext)
-               cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
+               rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
        else
-               cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+               rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+       if (rc && cifs_sb->tcon->ipc) {
+               cFYI(1, ("ipc connection - fake read inode"));
+               inode->i_mode |= S_IFDIR;
+               inode->i_nlink = 2;
+               inode->i_op = &cifs_ipc_inode_ops;
+               inode->i_fop = &simple_dir_operations;
+               inode->i_uid = cifs_sb->mnt_uid;
+               inode->i_gid = cifs_sb->mnt_gid;
+       }
+
        /* can not call macro FreeXid here since in a void func */
        _FreeXid(xid);
 }
index 0bcec0844bee8830099f9ae264e8cd65860bf012..51ec681fe74a2e32c19d90e2f45de591bb3ab048 100644 (file)
@@ -169,7 +169,6 @@ cifs_buf_get(void)
 void
 cifs_buf_release(void *buf_to_free)
 {
-
        if (buf_to_free == NULL) {
                /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
                return;