[linux-cifs-client] [PATCH 4/6] [CIFS] change cifs_setup_session to take a unc string arg

Jeff Layton jlayton at redhat.com
Wed Oct 31 15:31:36 GMT 2007


..then extract the host portion of the UNC string so that we can
use in SPNEGO.

Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
 fs/cifs/cifsproto.h |    2 +-
 fs/cifs/cifssmb.c   |    6 ++++--
 fs/cifs/connect.c   |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index dd1d7c2..b256e8a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -107,7 +107,7 @@ void cifs_proc_init(void);
 void cifs_proc_clean(void);
 
 extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
-			struct nls_table *nls_info);
+			struct nls_table *nls_info, const char *unc);
 extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
 
 extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0bb3e43..49ad995 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -157,7 +157,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
 			down(&tcon->ses->sesSem);
 			if (tcon->ses->status == CifsNeedReconnect)
 				rc = cifs_setup_session(0, tcon->ses,
-							nls_codepage);
+							nls_codepage,
+							tcon->treeName);
 			if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
 				mark_open_files_invalid(tcon);
 				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
@@ -302,7 +303,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
 			down(&tcon->ses->sesSem);
 			if (tcon->ses->status == CifsNeedReconnect)
 				rc = cifs_setup_session(0, tcon->ses,
-							nls_codepage);
+							nls_codepage,
+							tcon->treeName);
 			if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
 				mark_open_files_invalid(tcon);
 				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 19ee11f..057d55c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1996,7 +1996,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 			down(&pSesInfo->sesSem);
 			/* BB FIXME need to pass vol->secFlgs BB */
 			rc = cifs_setup_session(xid, pSesInfo,
-						cifs_sb->local_nls);
+						cifs_sb->local_nls,
+						volume_info.UNC);
 			up(&pSesInfo->sesSem);
 			if (!rc)
 				atomic_inc(&srvTcp->socketUseCount);
@@ -3508,13 +3509,51 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
 	return rc;	/* BB check if we should always return zero here */
 }
 
+/* extract the host portion of the UNC string */
+static char *
+extract_hostname_from_unc(const char *unc)
+{
+	const char *src;
+	char *dst, *delim;
+	unsigned int len;
+
+	/* skip double chars at beginning of string */
+	/* BB: check validity of these bytes? */
+	src = unc + 2;
+
+	delim = strchr(src, '/');
+	if (!delim) {
+		delim = strchr(src, '\\');
+		if (!delim)
+			return ERR_PTR(-EINVAL);
+	}
+
+	len = delim - src;
+	dst = kmalloc((len + 1), GFP_KERNEL);
+	if (dst == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(dst, src, len);
+	dst[len] = '\0';
+
+	return dst;
+}
+
 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
-					   struct nls_table *nls_info)
+			struct nls_table *nls_info, const char *unc)
 {
 	int rc = 0;
 	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
 	int first_time = 0;
+	char *hostname;
+
+	hostname = extract_hostname_from_unc(unc);
+	if (IS_ERR(hostname)) {
+		rc = PTR_ERR(hostname);
+		hostname = NULL;
+		goto ss_err_exit;
+	}
 
 	/* what if server changes its buffer size after dropping the session? */
 	if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
@@ -3627,6 +3666,9 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
 		}
 	}
 ss_err_exit:
+	if (hostname)
+		kfree(hostname);
+
 	return rc;
 }
 
-- 
1.5.2.1



More information about the linux-cifs-client mailing list