Re: dfs path construction fixup for / character in \\server\share component of dfs path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Steve French wrote:
> Attached is dfs path construction fixup for / character in
> \\server\share component of dfs path.  Let me know if you see any
> problem - but it gets Samba past the problem with not returning
> STATUS_PATH_NOT_COVERED
> 
> similar change will have to be made to build_full_dfs_path_from_dentry
> in cifs_dfs_ref.c
> 
> This makes it easier for me to test the remainder of the changes
> needed to the SMB GetDFSReferral function(s).  Has anyone checked on
> the answer to Al's question on submount expiry from a few days ago?


I've just tested it and the patch fixed a problem with the lack of 
STATUS_PATH_NOT_COVERED with unix-ext enabled on samba server.
1. samba with unix-ext enabled returns (5th packet) dfs link as a symbolic link,
but for dfs code it should be the directory type so we could fix it in the time 
of creating inode and get the server generated inode number.

No.     Time        Source                Destination           Protocol Info
      1 0.000000    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: //192.168.133.1/dfs/dfs2
      2 0.000385    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO, Error: STATUS_PATH_NOT_COVERED
      3 0.000670    192.168.133.129       192.168.133.1         TCP      46662 > microsoft-ds [ACK] Seq=127 Ack=40 Win=1728 Len=0 TSV=509648098 TSER=3625842022

      4 0.006911    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: /dfs2
      5 0.007110    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO

                                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - here our chance to get it working

      6 0.016002    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File Unix Link, Path: /dfs2
      7 0.016219    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO
      8 0.049621    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: //192.168.133.1/dfs/msdfs:\172.16.61.1\dfs2
      9 0.050706    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO, Error: STATUS_OBJECT_NAME_NOT_FOUND

Patches that make dfs working in this case are attached.



2. samba with unix-ext disabled returns STATUS_OBJECT_NAME_NOT_FOUND on the second
query (5th packet). Replacing '\' with '/' doesn't help. It looks we will not be 
able to make this case work unless we disable server generated inode numbers and fill
up junction point inode with fake values. Another way to make it working is to fix
samba code so that it would return inode info (with directory type) on the second call
as win2k does.

No.     Time        Source                Destination           Protocol Info
      1 0.000000    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File All Info, Path: \\192.168.133.1\dfs\dfs2
      2 0.000576    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO, Error: STATUS_PATH_NOT_COVERED
      3 0.000746    192.168.133.129       192.168.133.1         TCP      37925 > microsoft-ds [ACK] Seq=127 Ack=40 Win=1728 Len=0 TSV=510792731 TSER=3626976733

      4 0.004212    192.168.133.129       192.168.133.1         SMB      Trans2 Request, QUERY_PATH_INFO, Query File All Info, Path: \dfs2
      5 0.004606    192.168.133.1         192.168.133.129       SMB      Trans2 Response, QUERY_PATH_INFO, Error: STATUS_OBJECT_NAME_NOT_FOUND

-- 

Best regards,

-------------------------
Igor Mammedov,
niallain "at" gmail.com




>From deef01fdc817a0e0d167e28eabe30890fc789608 Mon Sep 17 00:00:00 2001
From: Igor Mammedov <niallain@xxxxxxxxx>
Date: Wed, 23 Apr 2008 17:34:28 +0400
Subject: [PATCH] Adds to dns_resolver checking if the server name is an IP addr and skipping upcall in this case.

Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx>
---
 fs/cifs/dns_resolve.c |   62 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 7cc86c4..939e256 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -55,6 +55,32 @@ struct key_type key_type_dns_resolver = {
 	.match       = user_match,
 };
 
+/* Checks if supplied name is IP address
+ * returns:
+ * 		1 - name is IP
+ * 		0 - name is not IP
+ */
+static int is_ip(const char *name)
+{
+	int rc;
+	struct sockaddr_in sin_server;
+	struct sockaddr_in6 sin_server6;
+
+	rc = cifs_inet_pton(AF_INET, name,
+			&sin_server.sin_addr.s_addr);
+
+	if (rc <= 0) {
+		/* not ipv4 address, try ipv6 */
+		rc = cifs_inet_pton(AF_INET6, name,
+				&sin_server6.sin6_addr.in6_u);
+		if (rc > 0)
+			return 1;
+	} else {
+		return 1;
+	}
+	/* we failed translating address */
+	return 0;
+}
 
 /* Resolves server name to ip address.
  * input:
@@ -67,8 +93,9 @@ int
 dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 {
 	int rc = -EAGAIN;
-	struct key *rkey;
+	struct key *rkey = ERR_PTR(-EAGAIN);
 	char *name;
+	char *data = NULL;
 	int len;
 
 	if (!ip_addr || !unc)
@@ -97,26 +124,41 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 	memcpy(name, unc+2, len);
 	name[len] = 0;
 
+	if (is_ip(name)) {
+		cFYI(1, ("%s: it is IP, skipping dns upcall: %s",
+					__func__, name));
+		data = name;
+		goto skip_upcall;
+	}
+
 	rkey = request_key(&key_type_dns_resolver, name, "");
 	if (!IS_ERR(rkey)) {
-		len = strlen(rkey->payload.data);
-		*ip_addr = kmalloc(len+1, GFP_KERNEL);
-		if (*ip_addr) {
-			memcpy(*ip_addr, rkey->payload.data, len);
-			(*ip_addr)[len] = '\0';
-			cFYI(1, ("%s: resolved: %s to %s", __func__,
+		data = rkey->payload.data;
+		cFYI(1, ("%s: resolved: %s to %s", __func__,
 					rkey->description,
 					*ip_addr
 				));
+	} else {
+		cERROR(1, ("%s: unable to resolve: %s", __func__, name));
+		goto out;
+	}
+
+skip_upcall:
+	if (data) {
+		len = strlen(data);
+		*ip_addr = kmalloc(len+1, GFP_KERNEL);
+		if (*ip_addr) {
+			memcpy(*ip_addr, data, len);
+			(*ip_addr)[len] = '\0';
 			rc = 0;
 		} else {
 			rc = -ENOMEM;
 		}
-		key_put(rkey);
-	} else {
-		cERROR(1, ("%s: unable to resolve: %s", __func__, name));
+		if (!IS_ERR(rkey))
+			key_put(rkey);
 	}
 
+out:
 	kfree(name);
 	return rc;
 }
-- 
1.5.3.7

>From d69f4d0a59086658491eec4f2e43a890c4357a29 Mon Sep 17 00:00:00 2001
From: Igor Mammedov <niallain@xxxxxxxxx>
Date: Wed, 23 Apr 2008 17:40:34 +0400
Subject: [PATCH] fixed compatibility issue with samba: a refferal request UNC is canonized to '/' path separator

Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx>
---
 fs/cifs/cifs_dfs_ref.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index f53f41f..bc110f7 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -81,15 +81,11 @@ static char *cifs_get_share_name(const char *node_name)
 	/* find sharename end */
 	pSep++;
 	pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC));
-	if (!pSep) {
-		cERROR(1, ("%s:2 cant find share name in node name: %s",
-			__func__, node_name));
-		kfree(UNC);
-		return NULL;
+	if (pSep) {
+		/* trim path up to sharename end
+		 * now we have share name in UNC */
+		*pSep = 0;
 	}
-	/* trim path up to sharename end
-	 *          * now we have share name in UNC */
-	*pSep = 0;
 
 	return UNC;
 }
@@ -176,7 +172,7 @@ static char *compose_mount_options(const char *sb_mountdata,
 		tkn_e = strchr(tkn_e+1, '\\');
 		if (tkn_e) {
 			strcat(mountdata, ",prefixpath=");
-			strcat(mountdata, tkn_e);
+			strcat(mountdata, tkn_e+1);
 		}
 	}
 
@@ -232,7 +228,8 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry)
 		return NULL;
 
 	if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) {
-		/* we should use full path name to correct working with DFS */
+		int i;
+		/* we should use full path name for correct working with DFS */
 		l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) +
 					strnlen(search_path, MAX_PATHCONF) + 1;
 		tmp_path = kmalloc(l_max_len, GFP_KERNEL);
@@ -243,6 +240,12 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry)
 		strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len);
 		strcat(tmp_path, search_path);
 		tmp_path[l_max_len-1] = 0;
+		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+			for (i = 0; i < l_max_len; i++) {
+				if (tmp_path[i] == '\\')
+					tmp_path[i] = '/';
+			}
+
 		full_path = tmp_path;
 		kfree(search_path);
 	} else {
-- 
1.5.3.7

>From e5914b5297d953ba3d08fb79bb82e0d890130218 Mon Sep 17 00:00:00 2001
From: Igor Mammedov <niallain@xxxxxxxxx>
Date: Wed, 23 Apr 2008 17:57:34 +0400
Subject: [PATCH] Workaround for working with samba (unix extentions mode enabled only).

Fixup inode from symlink to directory mode, so we could mount on it
a dfs submount.

Since samba in unix-ext mode returns a dfs junction point as a link,
we have a chance to get symlink info (including inode number) and
right after that fix inode mode from symlink to directory.
That looks wierd but DFS works (at least in the case when samba is
in unix-ext mode).`

Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx>
---
 fs/cifs/inode.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e1031b9..144879b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -261,6 +261,14 @@ try_again_CIFSSMBUnixQPathInfo:
 
 		cifs_unix_info_to_inode(inode, &findData, 0);
 
+		/* if it dfs link (i.e. we've got PATH_UNCOVERED error)
+		 * we need to fix up its type to the directory before
+		 * making it mount point */
+		if (is_dfs_referral && (inode->i_mode & S_IFMT & S_IFLNK)) {
+			inode->i_mode &= ~S_IFLNK;
+			inode->i_mode |= S_IFDIR;
+			cFYI(1, ("faking dir type for the dfs link"));
+		}
 
 		if (num_of_bytes < end_of_file)
 			cFYI(1, ("allocation size less than end of file"));
-- 
1.5.3.7


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux