* [PATCH v3 0/7] Add support for DFS in SMB2+
@ 2017-02-28 18:40 Aurelien Aptel
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
0 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
This series of patch tries to implement the get_dfs_refer operation
for SMB2+.
In SMB2+, DFS resolving is now done through an FSCTL (patch #7). The
relevant Microsoft specifications for this are:
MS-SMB2: 3.2.4.20 Application Requests an IO Control Code Operation
MS-SMB2: 3.2.4.20.3 Application Requests DFS Referral Information
MS-SMB2: 3.2.5.14 Receiving an SMB2 IOCTL Response
MS-SMB2: 3.2.5.14.4 Handling a DFS Referral Information Response
MS-DFSC: 2.2 Message Syntax (but really the whole document is useful)
The DFS response payload however is identical. Patch #1 moves the
DFS response parsing out of SMB1 code and makes it work on any version
of SMB.
DFS code has 2 "main" entry points: initial mounting and automount
(when a DFS link is accessed/traversed).
When automounting, cifs.ko calls build_path_from_dentry() which only
makes treename-prefixed paths when the tcon has the
SMB_IN_DFS_SHARE. This flag is checked in tcon->Flags which is never
touched by SMB2 code as it sets tcon->share_flags on connexion.
* CIFS requires to prefix all pathnames with the treename prefix when
connected to a DFS server, so the current build_path_from_dentry()
makes sense for CIFS.
* For SMB2+ it seems only the Create request requires the treename
prefix. Simply making the function check for both CIFS SMB2+ flag
for DFS to add a prefix does not work as the server has different
expectations about which packet can have/require a DFS pathname.
Patch #2 adds build_path_from_dentry_optional_prefix() with an extra
bool arg to decide to prefix or not. The automount code path always
ask for it. Patch #6 modifies SMB2_open() to add the treename prefix
to the given path if the server requires it.
We try to use an IPC connection first for the DFS request. Patch #3
adds a flag to SMB2_ioctl() to force the usage of ipc_tid. The SMB2
get_dfs_refer operation tries with the flag set and fallback to a
share connection if that doesn't work.
Patch #4 updates the type of ipc_tid from u16 to u32 as that is what a
Tid is in SMB2+. This is correct and really needed since in SMB2 Samba
doesn't use sequential tree id but random ones in the 32bit space.
As part of the mouting process a IPC tcon is made (I suspect we don't
need it anymore in SMB3). This tcon doesn't respect the signing
requirement. This is fixed by patch #5.
Finally the SMB2+ implementation of the get_dfs_referral operation is
added in all supported SMB versions in patch #7.
I've sucessfuly tested this (v1.0 and v3.0) against a Windows Server
2016 DFS setup and a Samba DFS setup.
Samba used to only accepts DFS referrals requests on an IPC connexion,
which is in violation of the spec. A patch was sent on samba-technical
and merged. It is not required anymore.
https://lists.samba.org/archive/samba-technical/2017-February/118859.html
Changes since v2:
* add use_ipc flag to SMB2_open()
* make smb2_get_dfs_refer() try IPC connections first
* use first_entry_or_null() instead of first_entry() on the tcon list
* protect tcon list access with spinlock
* add inc/dec of the tcon reference number, protected by spinlock
Aurelien Aptel (7):
CIFS: move DFS response parsing out of SMB1 code
CIFS: add build_path_from_dentry_optional_prefix()
CIFS: add use_ipc flag to SMB2_ioctl()
CIFS: let ses->ipc_tid hold smb2 TreeIds
CIFS: set signing flag in SMB2+ TreeConnect if needed
CIFS: use DFS pathnames in SMB2+ Create requests
CIFS: implement get_dfs_refer for SMB2+
fs/cifs/cifs_dfs_ref.c | 4 +-
fs/cifs/cifsglob.h | 2 +-
fs/cifs/cifspdu.h | 16 ++++---
fs/cifs/cifsproto.h | 7 +++
fs/cifs/cifssmb.c | 119 ++---------------------------------------------
fs/cifs/dir.c | 13 +++++-
fs/cifs/misc.c | 105 +++++++++++++++++++++++++++++++++++++++++
fs/cifs/smb2file.c | 3 +-
fs/cifs/smb2ops.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++---
fs/cifs/smb2pdu.c | 114 +++++++++++++++++++++++++++++++++++++--------
fs/cifs/smb2pdu.h | 8 ++++
fs/cifs/smb2proto.h | 3 +-
12 files changed, 365 insertions(+), 152 deletions(-)
--
2.10.2
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 1/7] CIFS: move DFS response parsing out of SMB1 code
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-2-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 2/7] CIFS: add build_path_from_dentry_optional_prefix() Aurelien Aptel
` (6 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
since the DFS payload is not tied to the SMB version we can:
* isolate the DFS payload in its own struct, and include that struct in
packet structs
* move the function that parses the response to misc.c and make it work
on the new DFS payload struct (add payload size and utf16 flag as a
result).
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/cifspdu.h | 16 ++++---
fs/cifs/cifsproto.h | 5 +++
fs/cifs/cifssmb.c | 119 +++-------------------------------------------------
fs/cifs/misc.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 125 insertions(+), 120 deletions(-)
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index f5b8730..1ce733f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2086,17 +2086,21 @@ typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
__u8 ServiceSiteGuid[16]; /* MBZ, ignored */
} __attribute__((packed)) REFERRAL3;
-typedef struct smb_com_transaction_get_dfs_refer_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u8 Pad;
+struct get_dfs_referral_rsp {
__le16 PathConsumed;
__le16 NumberOfReferrals;
__le32 DFSFlags;
REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
/* followed by the strings pointed to by the referral structures */
-} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP;
+} __packed;
+
+typedef struct smb_com_transaction_get_dfs_refer_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u8 Pad;
+ struct get_dfs_referral_rsp dfs_data;
+} __packed TRANSACTION2_GET_DFS_REFER_RSP;
/* DFS Flags */
#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 406d2c1..c097830 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -284,6 +284,11 @@ extern int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
const struct nls_table *nls_codepage,
unsigned int *num_referrals,
struct dfs_info3_param **referrals, int remap);
+extern int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
+ unsigned int *num_of_nodes,
+ struct dfs_info3_param **target_nodes,
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName, bool is_unicode);
extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
struct smb_vol *vol);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f5099fb..5005c79 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4786,117 +4786,6 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
-/* parses DFS refferal V3 structure
- * caller is responsible for freeing target_nodes
- * returns:
- * on success - 0
- * on failure - errno
- */
-static int
-parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
- unsigned int *num_of_nodes,
- struct dfs_info3_param **target_nodes,
- const struct nls_table *nls_codepage, int remap,
- const char *searchName)
-{
- int i, rc = 0;
- char *data_end;
- bool is_unicode;
- struct dfs_referral_level_3 *ref;
-
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- is_unicode = true;
- else
- is_unicode = false;
- *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
-
- if (*num_of_nodes < 1) {
- cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
- *num_of_nodes);
- rc = -EINVAL;
- goto parse_DFS_referrals_exit;
- }
-
- ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
- if (ref->VersionNumber != cpu_to_le16(3)) {
- cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
- le16_to_cpu(ref->VersionNumber));
- rc = -EINVAL;
- goto parse_DFS_referrals_exit;
- }
-
- /* get the upper boundary of the resp buffer */
- data_end = (char *)(&(pSMBr->PathConsumed)) +
- le16_to_cpu(pSMBr->t2.DataCount);
-
- cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
- *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
-
- *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
- GFP_KERNEL);
- if (*target_nodes == NULL) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- /* collect necessary data from referrals */
- for (i = 0; i < *num_of_nodes; i++) {
- char *temp;
- int max_len;
- struct dfs_info3_param *node = (*target_nodes)+i;
-
- node->flags = le32_to_cpu(pSMBr->DFSFlags);
- if (is_unicode) {
- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
- GFP_KERNEL);
- if (tmp == NULL) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
- cifsConvertToUTF16((__le16 *) tmp, searchName,
- PATH_MAX, nls_codepage, remap);
- node->path_consumed = cifs_utf16_bytes(tmp,
- le16_to_cpu(pSMBr->PathConsumed),
- nls_codepage);
- kfree(tmp);
- } else
- node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
-
- node->server_type = le16_to_cpu(ref->ServerType);
- node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
-
- /* copy DfsPath */
- temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
- max_len = data_end - temp;
- node->path_name = cifs_strndup_from_utf16(temp, max_len,
- is_unicode, nls_codepage);
- if (!node->path_name) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- /* copy link target UNC */
- temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
- max_len = data_end - temp;
- node->node_name = cifs_strndup_from_utf16(temp, max_len,
- is_unicode, nls_codepage);
- if (!node->node_name) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- ref++;
- }
-
-parse_DFS_referrals_exit:
- if (rc) {
- free_dfs_info_array(*target_nodes, *num_of_nodes);
- *target_nodes = NULL;
- *num_of_nodes = 0;
- }
- return rc;
-}
-
int
CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
const char *search_name, struct dfs_info3_param **target_nodes,
@@ -4993,9 +4882,11 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
/* parse returned result into more usable form */
- rc = parse_DFS_referrals(pSMBr, num_of_nodes,
- target_nodes, nls_codepage, remap,
- search_name);
+ rc = parse_dfs_referrals(&pSMBr->dfs_data,
+ le16_to_cpu(pSMBr->t2.DataCount),
+ num_of_nodes, target_nodes, nls_codepage,
+ remap, search_name,
+ pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
GetDFSRefExit:
cifs_buf_release(pSMB);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index c672915..d3fb115 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -640,3 +640,108 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
cifs_add_pending_open_locked(fid, tlink, open);
spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
}
+
+/* parses DFS refferal V3 structure
+ * caller is responsible for freeing target_nodes
+ * returns:
+ * - on success - 0
+ * - on failure - errno
+ */
+int
+parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
+ unsigned int *num_of_nodes,
+ struct dfs_info3_param **target_nodes,
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName, bool is_unicode)
+{
+ int i, rc = 0;
+ char *data_end;
+ struct dfs_referral_level_3 *ref;
+
+ *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
+
+ if (*num_of_nodes < 1) {
+ cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
+ *num_of_nodes);
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
+ if (ref->VersionNumber != cpu_to_le16(3)) {
+ cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
+ le16_to_cpu(ref->VersionNumber));
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* get the upper boundary of the resp buffer */
+ data_end = (char *)rsp + rsp_size;
+
+ cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
+ *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
+
+ *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
+ GFP_KERNEL);
+ if (*target_nodes == NULL) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* collect necessary data from referrals */
+ for (i = 0; i < *num_of_nodes; i++) {
+ char *temp;
+ int max_len;
+ struct dfs_info3_param *node = (*target_nodes)+i;
+
+ node->flags = le32_to_cpu(rsp->DFSFlags);
+ if (is_unicode) {
+ __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
+ GFP_KERNEL);
+ if (tmp == NULL) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+ cifsConvertToUTF16((__le16 *) tmp, searchName,
+ PATH_MAX, nls_codepage, remap);
+ node->path_consumed = cifs_utf16_bytes(tmp,
+ le16_to_cpu(rsp->PathConsumed),
+ nls_codepage);
+ kfree(tmp);
+ } else
+ node->path_consumed = le16_to_cpu(rsp->PathConsumed);
+
+ node->server_type = le16_to_cpu(ref->ServerType);
+ node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
+
+ /* copy DfsPath */
+ temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
+ max_len = data_end - temp;
+ node->path_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
+ if (!node->path_name) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* copy link target UNC */
+ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
+ max_len = data_end - temp;
+ node->node_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
+ if (!node->node_name) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ ref++;
+ }
+
+parse_DFS_referrals_exit:
+ if (rc) {
+ free_dfs_info_array(*target_nodes, *num_of_nodes);
+ *target_nodes = NULL;
+ *num_of_nodes = 0;
+ }
+ return rc;
+}
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 2/7] CIFS: add build_path_from_dentry_optional_prefix()
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 1/7] CIFS: move DFS response parsing out of SMB1 code Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-3-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 3/7] CIFS: add use_ipc flag to SMB2_ioctl() Aurelien Aptel
` (5 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
this function does the same thing as add build_path_from_dentry() but
takes a boolean parameter to decide whether or not to prefix the path
with the tree name.
we cannot rely on tcon->Flags & SMB_SHARE_IS_IN_DFS for SMB2 as smb2
code never sets tcon->Flags but it sets tcon->share_flags and it seems
the SMB_SHARE_IS_IN_DFS has different semantics in SMB2: the prefix
shouldn't be added everytime it was in SMB1.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/cifs_dfs_ref.c | 4 +++-
fs/cifs/cifsproto.h | 2 ++
fs/cifs/dir.c | 13 ++++++++++++-
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index ec9dbbc..8a9ebfd 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -302,7 +302,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
* gives us the latter, so we must adjust the result.
*/
mnt = ERR_PTR(-ENOMEM);
- full_path = build_path_from_dentry(mntpt);
+
+ /* always use tree name prefix */
+ full_path = build_path_from_dentry_optional_prefix(mntpt, true);
if (full_path == NULL)
goto cdda_exit;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c097830..9ee46c1 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -61,6 +61,8 @@ extern void exit_cifs_idmap(void);
extern int init_cifs_spnego(void);
extern void exit_cifs_spnego(void);
extern char *build_path_from_dentry(struct dentry *);
+extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
+ bool prefix);
extern char *cifs_build_path_to_root(struct smb_vol *vol,
struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 2c227a9..56366e9 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -81,6 +81,17 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
char *
build_path_from_dentry(struct dentry *direntry)
{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
+
+ return build_path_from_dentry_optional_prefix(direntry,
+ prefix);
+}
+
+char *
+build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
+{
struct dentry *temp;
int namelen;
int dfsplen;
@@ -92,7 +103,7 @@ build_path_from_dentry(struct dentry *direntry)
unsigned seq;
dirsep = CIFS_DIR_SEP(cifs_sb);
- if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+ if (prefix)
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 3/7] CIFS: add use_ipc flag to SMB2_ioctl()
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 1/7] CIFS: move DFS response parsing out of SMB1 code Aurelien Aptel
2017-02-28 18:40 ` [PATCH v3 2/7] CIFS: add build_path_from_dentry_optional_prefix() Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-4-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 4/7] CIFS: let ses->ipc_tid hold smb2 TreeIds Aurelien Aptel
` (4 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
when set, use the session IPC tree id instead of the tid in the provided
tcon.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/smb2file.c | 3 ++-
fs/cifs/smb2ops.c | 23 ++++++++++++++++-------
fs/cifs/smb2pdu.c | 17 +++++++++++++++--
fs/cifs/smb2proto.h | 3 ++-
4 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index b2aff0c..b4b1f03 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -73,7 +73,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
nr_ioctl_req.Reserved = 0;
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
- fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true,
+ fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
+ true /* is_fsctl */, false /* use_ipc */,
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
NULL, NULL /* no return info */);
if (rc == -EOPNOTSUPP) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index a44b4db..02937cc 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -282,6 +282,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
+ false /* use_ipc */,
NULL /* no data input */, 0 /* no data input */,
(char **)&out_buf, &ret_data_len);
if (rc != 0)
@@ -571,6 +572,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
+ false /* use_ipc */,
NULL, 0 /* no input */,
(char **)&res_key, &ret_data_len);
@@ -635,7 +637,8 @@ smb2_clone_range(const unsigned int xid,
/* Request server copy to target from src identified by key */
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
- true /* is_fsctl */, (char *)pcchunk,
+ true /* is_fsctl */, false /* use_ipc */,
+ (char *)pcchunk,
sizeof(struct copychunk_ioctl), (char **)&retbuf,
&ret_data_len);
if (rc == 0) {
@@ -787,7 +790,8 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
- true /* is_fctl */, &setsparse, 1, NULL, NULL);
+ true /* is_fctl */, false /* use_ipc */,
+ &setsparse, 1, NULL, NULL);
if (rc) {
tcon->broken_sparse_sup = true;
cifs_dbg(FYI, "set sparse rc = %d\n", rc);
@@ -857,7 +861,8 @@ smb2_duplicate_extents(const unsigned int xid,
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
trgtfile->fid.volatile_fid,
FSCTL_DUPLICATE_EXTENTS_TO_FILE,
- true /* is_fsctl */, (char *)&dup_ext_buf,
+ true /* is_fsctl */, false /* use_ipc */,
+ (char *)&dup_ext_buf,
sizeof(struct duplicate_extents_to_file),
NULL,
&ret_data_len);
@@ -891,7 +896,8 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid,
FSCTL_SET_INTEGRITY_INFORMATION,
- true /* is_fsctl */, (char *)&integr_info,
+ true /* is_fsctl */, false /* use_ipc */,
+ (char *)&integr_info,
sizeof(struct fsctl_set_integrity_information_req),
NULL,
&ret_data_len);
@@ -910,7 +916,8 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid,
FSCTL_SRV_ENUMERATE_SNAPSHOTS,
- true /* is_fsctl */, NULL, 0 /* no input data */,
+ true /* is_fsctl */, false /* use_ipc */,
+ NULL, 0 /* no input data */,
(char **)&retbuf,
&ret_data_len);
cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
@@ -1220,7 +1227,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
- true /* is_fctl */, (char *)&fsctl_buf,
+ true /* is_fctl */, false /* use_ipc */,
+ (char *)&fsctl_buf,
sizeof(struct file_zero_data_information), NULL, NULL);
free_xid(xid);
return rc;
@@ -1254,7 +1262,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
- true /* is_fctl */, (char *)&fsctl_buf,
+ true /* is_fctl */, false /* use_ipc */,
+ (char *)&fsctl_buf,
sizeof(struct file_zero_data_information), NULL, NULL);
free_xid(xid);
return rc;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index ad83b3d..8c4532d 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -620,6 +620,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
+ false /* use_ipc */,
(char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req),
(char **)&pneg_rsp, &rsplen);
@@ -1683,8 +1684,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
*/
int
SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
- u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data,
- u32 indatalen, char **out_data, u32 *plen /* returned data len */)
+ u64 volatile_fid, u32 opcode, bool is_fsctl, bool use_ipc,
+ char *in_data, u32 indatalen,
+ char **out_data, u32 *plen /* returned data len */)
{
struct smb2_ioctl_req *req;
struct smb2_ioctl_rsp *rsp;
@@ -1721,6 +1723,16 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
if (rc)
return rc;
+ if (use_ipc) {
+ if (ses->ipc_tid == 0) {
+ cifs_small_buf_release(req);
+ return -ENOTCONN;
+ }
+
+ cifs_dbg(FYI, "replacing tid 0x%x with IPC tid 0x%x\n",
+ req->hdr.sync_hdr.TreeId, ses->ipc_tid);
+ req->hdr.sync_hdr.TreeId = ses->ipc_tid;
+ }
if (encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;
@@ -1843,6 +1855,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
FSCTL_SET_COMPRESSION, true /* is_fsctl */,
+ false /* use_ipc */,
(char *)&fsctl_input /* data input */,
2 /* in data len */, &ret_data /* out data */, NULL);
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 85fc7a7..11d9f30 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -121,7 +121,8 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
struct smb2_err_rsp **err_buf);
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 opcode,
- bool is_fsctl, char *in_data, u32 indatalen,
+ bool is_fsctl, bool use_ipc,
+ char *in_data, u32 indatalen,
char **out_data, u32 *plen /* returned data len */);
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id);
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 4/7] CIFS: let ses->ipc_tid hold smb2 TreeIds
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
` (2 preceding siblings ...)
2017-02-28 18:40 ` [PATCH v3 3/7] CIFS: add use_ipc flag to SMB2_ioctl() Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-5-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 5/7] CIFS: set signing flag in SMB2+ TreeConnect if needed Aurelien Aptel
` (3 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
the TreeId field went from 2 bytes in CIFS to 4 bytes in SMB2+. this
commit updates the size of the ipc_tid field of a cifs_ses, which was
still using 2 bytes.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/cifsglob.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1a90bb3..af224cd 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -822,7 +822,7 @@ struct cifs_ses {
int ses_count; /* reference counter */
enum statusEnum status;
unsigned overrideSecFlg; /* if non-zero override global sec flags */
- __u16 ipc_tid; /* special tid for connection to IPC share */
+ __u32 ipc_tid; /* special tid for connection to IPC share */
char *serverOS; /* name of operating system underlying server */
char *serverNOS; /* name of network operating system of server */
char *serverDomain; /* security realm of server */
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 5/7] CIFS: set signing flag in SMB2+ TreeConnect if needed
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
` (3 preceding siblings ...)
2017-02-28 18:40 ` [PATCH v3 4/7] CIFS: let ses->ipc_tid hold smb2 TreeIds Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-6-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 6/7] CIFS: use DFS pathnames in SMB2+ Create requests Aurelien Aptel
` (2 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
cifs_enable_signing() already sets server->sign according to what the
server requires/offers and what mount options allows/forbids, so use
that.
this is required for IPC tcon that connects to signing-required servers.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/smb2pdu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 8c4532d..2fd93ee 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1168,8 +1168,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
/* since no tcon, smb2_init can not do this, so do here */
req->hdr.sync_hdr.SessionId = ses->Suid;
- /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
- req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
+ if (ses->server->sign)
+ req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
} else if (encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 6/7] CIFS: use DFS pathnames in SMB2+ Create requests
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
` (4 preceding siblings ...)
2017-02-28 18:40 ` [PATCH v3 5/7] CIFS: set signing flag in SMB2+ TreeConnect if needed Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-7-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+ Aurelien Aptel
2017-03-02 4:41 ` [PATCH v3 0/7] Add support for DFS in SMB2+ Steve French
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
When connected to a DFS capable share, the client must set the
SMB2_FLAGS_DFS_OPERATIONS flag in the SMB2 header and use
DFS path names: "<server>\<share>\<path>" *without* leading \\.
Sources:
[MS-SMB2] 3.2.5.5 Receiving an SMB2 TREE_CONNECT Response
> TreeConnect.IsDfsShare MUST be set to TRUE, if the SMB2_SHARE_CAP_DFS
> bit is set in the Capabilities field of the response.
[MS-SMB2] 3.2.4.3 Application Requests Opening a File
> If TreeConnect.IsDfsShare is TRUE, the SMB2_FLAGS_DFS_OPERATIONS flag
> is set in the Flags field.
[MS-SMB2] 2.2.13 SMB2 CREATE Request, NameOffset:
> If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of the SMB2
> header, the file name includes a prefix that will be processed during
> DFS name normalization as specified in section 3.3.5.9. Otherwise, the
> file name is relative to the share that is identified by the TreeId in
> the SMB2 header.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/smb2pdu.c | 93 +++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 77 insertions(+), 16 deletions(-)
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 2fd93ee..059da05 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1528,6 +1528,48 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
return 0;
}
+static int
+alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
+ const char *treename, const __le16 *path)
+{
+ int treename_len, path_len;
+ const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
+
+ /*
+ * skip leading "\\"
+ */
+ treename_len = strlen(treename);
+ if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
+ return -EINVAL;
+
+ treename += 2;
+ treename_len -= 2;
+
+ path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
+
+ /*
+ * make room for one path separator between the treename and
+ * path
+ */
+ *out_len = treename_len + 1 + path_len;
+
+ /*
+ * final path needs to be null-terminated UTF16 with a
+ * size aligned to 8
+ */
+
+ *out_size = roundup((*out_len+1)*2, 8);
+ *out_path = kzalloc(*out_size, GFP_KERNEL);
+ if (!*out_path)
+ return -ENOMEM;
+
+ cifs_strtoUTF16(*out_path, treename, treename_len, load_nls_default());
+ UniStrcat(*out_path, sep);
+ UniStrcat(*out_path, path);
+
+ return 0;
+}
+
int
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
__u8 *oplock, struct smb2_file_all_info *buf,
@@ -1576,30 +1618,49 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
req->ShareAccess = FILE_SHARE_ALL_LE;
req->CreateDisposition = cpu_to_le32(oparms->disposition);
req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
- uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
- /* do not count rfc1001 len field */
- req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
iov[0].iov_base = (char *)req;
/* 4 for rfc1002 length field */
iov[0].iov_len = get_rfc1002_length(req) + 4;
-
- /* MUST set path len (NameLength) to 0 opening root of share */
- req->NameLength = cpu_to_le16(uni_path_len - 2);
/* -1 since last byte is buf[0] which is sent below (path) */
iov[0].iov_len--;
- if (uni_path_len % 8 != 0) {
- copy_size = uni_path_len / 8 * 8;
- if (copy_size < uni_path_len)
- copy_size += 8;
-
- copy_path = kzalloc(copy_size, GFP_KERNEL);
- if (!copy_path)
- return -ENOMEM;
- memcpy((char *)copy_path, (const char *)path,
- uni_path_len);
+
+ req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
+
+ /* [MS-SMB2] 2.2.13 NameOffset:
+ * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
+ * the SMB2 header, the file name includes a prefix that will
+ * be processed during DFS name normalization as specified in
+ * section 3.3.5.9. Otherwise, the file name is relative to
+ * the share that is identified by the TreeId in the SMB2
+ * header.
+ */
+ if (tcon->share_flags & SHI1005_FLAGS_DFS) {
+ int name_len;
+
+ req->hdr.sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
+ rc = alloc_path_with_tree_prefix(©_path, ©_size,
+ &name_len,
+ tcon->treeName, path);
+ if (rc)
+ return rc;
+ req->NameLength = cpu_to_le16(name_len * 2);
uni_path_len = copy_size;
path = copy_path;
+ } else {
+ uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
+ /* MUST set path len (NameLength) to 0 opening root of share */
+ req->NameLength = cpu_to_le16(uni_path_len - 2);
+ if (uni_path_len % 8 != 0) {
+ copy_size = roundup(uni_path_len, 8);
+ copy_path = kzalloc(copy_size, GFP_KERNEL);
+ if (!copy_path)
+ return -ENOMEM;
+ memcpy((char *)copy_path, (const char *)path,
+ uni_path_len);
+ uni_path_len = copy_size;
+ path = copy_path;
+ }
}
iov[1].iov_len = uni_path_len;
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
` (5 preceding siblings ...)
2017-02-28 18:40 ` [PATCH v3 6/7] CIFS: use DFS pathnames in SMB2+ Create requests Aurelien Aptel
@ 2017-02-28 18:40 ` Aurelien Aptel
[not found] ` <20170228184034.18771-8-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-02 4:41 ` [PATCH v3 0/7] Add support for DFS in SMB2+ Steve French
7 siblings, 1 reply; 19+ messages in thread
From: Aurelien Aptel @ 2017-02-28 18:40 UTC (permalink / raw)
To: linux-cifs-u79uwXL29TY76Z2rM5mHXA; +Cc: Aurelien Aptel
in SMB2+ the get_dfs_refer operation uses a FSCTL. The request can be
made on any Tree Connection according to the specs. Since Samba only
accepted it on an IPC connection until recently, try that first.
https://lists.samba.org/archive/samba-technical/2017-February/118859.html
3.2.4.20.3 Application Requests DFS Referral Information:
> The client MUST search for an existing Session and TreeConnect to any
> share on the server identified by ServerName for the user identified by
> UserCredentials. If no Session and TreeConnect are found, the client
> MUST establish a new Session and TreeConnect to IPC$ on the target
> server as described in section 3.2.4.2 using the supplied ServerName and
> UserCredentials.
Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
---
fs/cifs/smb2ops.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/smb2pdu.h | 8 +++++
2 files changed, 108 insertions(+)
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 02937cc..fcd524d 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1104,6 +1104,102 @@ smb2_new_lease_key(struct cifs_fid *fid)
generate_random_uuid(fid->lease_key);
}
+static int
+smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
+ const char *search_name,
+ struct dfs_info3_param **target_nodes,
+ unsigned int *num_of_nodes,
+ const struct nls_table *nls_codepage, int remap)
+{
+ int rc;
+ __le16 *utf16_path = NULL;
+ int utf16_path_len = 0;
+ struct cifs_tcon *tcon;
+ struct fsctl_get_dfs_referral_req *dfs_req = NULL;
+ struct get_dfs_referral_rsp *dfs_rsp = NULL;
+ u32 dfs_req_size = 0, dfs_rsp_size = 0;
+
+ cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
+
+ /*
+ * Use any tcon from the current session. Here, the first one.
+ */
+ spin_lock(&cifs_tcp_ses_lock);
+ tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, tcon_list);
+ if (tcon)
+ tcon->tc_count++;
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ if (!tcon) {
+ cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
+ ses);
+ rc = -ENOTCONN;
+ goto out;
+ }
+
+ utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
+ &utf16_path_len,
+ nls_codepage, remap);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
+ dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
+ if (!dfs_req) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Highest DFS referral version understood */
+ dfs_req->MaxReferralLevel = cpu_to_le16(DFS_VERSION);
+
+ /* Path to resolve in an UTF-16 null-terminated string */
+ memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
+
+ do {
+ /* try first with IPC */
+ rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ FSCTL_DFS_GET_REFERRALS,
+ true /* is_fsctl */, true /* use_ipc */,
+ (char *)dfs_req, dfs_req_size,
+ (char **)&dfs_rsp, &dfs_rsp_size);
+ if (rc == -ENOTCONN) {
+ /* try with normal tcon */
+ rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ FSCTL_DFS_GET_REFERRALS,
+ true /* is_fsctl */, false /*use_ipc*/,
+ (char *)dfs_req, dfs_req_size,
+ (char **)&dfs_rsp, &dfs_rsp_size);
+ }
+ } while (rc == -EAGAIN);
+
+ if (rc) {
+ cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
+ goto out;
+ }
+
+ rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
+ num_of_nodes, target_nodes,
+ nls_codepage, remap, search_name,
+ true /* is_unicode */);
+ if (rc) {
+ cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc);
+ goto out;
+ }
+
+ out:
+ if (tcon) {
+ spin_lock(&cifs_tcp_ses_lock);
+ tcon->tc_count--;
+ spin_unlock(&cifs_tcp_ses_lock);
+ }
+ kfree(utf16_path);
+ kfree(dfs_req);
+ kfree(dfs_rsp);
+ return rc;
+}
#define SMB2_SYMLINK_STRUCT_SIZE \
(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
@@ -2263,6 +2359,7 @@ struct smb_version_operations smb20_operations = {
.clone_range = smb2_clone_range,
.wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close,
+ .get_dfs_refer = smb2_get_dfs_refer,
};
struct smb_version_operations smb21_operations = {
@@ -2344,6 +2441,7 @@ struct smb_version_operations smb21_operations = {
.wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close,
.enum_snapshots = smb3_enum_snapshots,
+ .get_dfs_refer = smb2_get_dfs_refer,
};
struct smb_version_operations smb30_operations = {
@@ -2435,6 +2533,7 @@ struct smb_version_operations smb30_operations = {
.free_transform_rq = smb3_free_transform_rq,
.is_transform_hdr = smb3_is_transform_hdr,
.receive_transform = smb3_receive_transform,
+ .get_dfs_refer = smb2_get_dfs_refer,
};
#ifdef CONFIG_CIFS_SMB311
@@ -2527,6 +2626,7 @@ struct smb_version_operations smb311_operations = {
.free_transform_rq = smb3_free_transform_rq,
.is_transform_hdr = smb3_is_transform_hdr,
.receive_transform = smb3_receive_transform,
+ .get_dfs_refer = smb2_get_dfs_refer,
};
#endif /* CIFS_SMB311 */
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index c03b252..18700fd 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -695,6 +695,14 @@ struct fsctl_get_integrity_information_rsp {
/* Integrity flags for above */
#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
+/* See MS-DFSC 2.2.2 */
+struct fsctl_get_dfs_referral_req {
+ __le16 MaxReferralLevel;
+ __u8 RequestFileName[];
+} __packed;
+
+/* DFS response is struct get_dfs_refer_rsp */
+
/* See MS-SMB2 2.2.31.3 */
struct network_resiliency_req {
__le32 Timeout;
--
2.10.2
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/7] CIFS: move DFS response parsing out of SMB1 code
[not found] ` <20170228184034.18771-2-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 1:58 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 1:58 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> since the DFS payload is not tied to the SMB version we can:
> * isolate the DFS payload in its own struct, and include that struct in
> packet structs
> * move the function that parses the response to misc.c and make it work
> on the new DFS payload struct (add payload size and utf16 flag as a
> result).
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/cifspdu.h | 16 ++++---
> fs/cifs/cifsproto.h | 5 +++
> fs/cifs/cifssmb.c | 119 +++-------------------------------------------------
> fs/cifs/misc.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 125 insertions(+), 120 deletions(-)
>
> diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
> index f5b8730..1ce733f 100644
> --- a/fs/cifs/cifspdu.h
> +++ b/fs/cifs/cifspdu.h
> @@ -2086,17 +2086,21 @@ typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
> __u8 ServiceSiteGuid[16]; /* MBZ, ignored */
> } __attribute__((packed)) REFERRAL3;
>
> -typedef struct smb_com_transaction_get_dfs_refer_rsp {
> - struct smb_hdr hdr; /* wct = 10 */
> - struct trans2_resp t2;
> - __u16 ByteCount;
> - __u8 Pad;
> +struct get_dfs_referral_rsp {
> __le16 PathConsumed;
> __le16 NumberOfReferrals;
> __le32 DFSFlags;
> REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
> /* followed by the strings pointed to by the referral structures */
> -} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP;
> +} __packed;
> +
> +typedef struct smb_com_transaction_get_dfs_refer_rsp {
> + struct smb_hdr hdr; /* wct = 10 */
> + struct trans2_resp t2;
> + __u16 ByteCount;
> + __u8 Pad;
> + struct get_dfs_referral_rsp dfs_data;
> +} __packed TRANSACTION2_GET_DFS_REFER_RSP;
>
> /* DFS Flags */
> #define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 406d2c1..c097830 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -284,6 +284,11 @@ extern int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
> const struct nls_table *nls_codepage,
> unsigned int *num_referrals,
> struct dfs_info3_param **referrals, int remap);
> +extern int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
> + unsigned int *num_of_nodes,
> + struct dfs_info3_param **target_nodes,
> + const struct nls_table *nls_codepage, int remap,
> + const char *searchName, bool is_unicode);
> extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
> struct cifs_sb_info *cifs_sb,
> struct smb_vol *vol);
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index f5099fb..5005c79 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -4786,117 +4786,6 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
> return rc;
> }
>
> -/* parses DFS refferal V3 structure
> - * caller is responsible for freeing target_nodes
> - * returns:
> - * on success - 0
> - * on failure - errno
> - */
> -static int
> -parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
> - unsigned int *num_of_nodes,
> - struct dfs_info3_param **target_nodes,
> - const struct nls_table *nls_codepage, int remap,
> - const char *searchName)
> -{
> - int i, rc = 0;
> - char *data_end;
> - bool is_unicode;
> - struct dfs_referral_level_3 *ref;
> -
> - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
> - is_unicode = true;
> - else
> - is_unicode = false;
> - *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
> -
> - if (*num_of_nodes < 1) {
> - cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
> - *num_of_nodes);
> - rc = -EINVAL;
> - goto parse_DFS_referrals_exit;
> - }
> -
> - ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
> - if (ref->VersionNumber != cpu_to_le16(3)) {
> - cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
> - le16_to_cpu(ref->VersionNumber));
> - rc = -EINVAL;
> - goto parse_DFS_referrals_exit;
> - }
> -
> - /* get the upper boundary of the resp buffer */
> - data_end = (char *)(&(pSMBr->PathConsumed)) +
> - le16_to_cpu(pSMBr->t2.DataCount);
> -
> - cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
> - *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
> -
> - *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
> - GFP_KERNEL);
> - if (*target_nodes == NULL) {
> - rc = -ENOMEM;
> - goto parse_DFS_referrals_exit;
> - }
> -
> - /* collect necessary data from referrals */
> - for (i = 0; i < *num_of_nodes; i++) {
> - char *temp;
> - int max_len;
> - struct dfs_info3_param *node = (*target_nodes)+i;
> -
> - node->flags = le32_to_cpu(pSMBr->DFSFlags);
> - if (is_unicode) {
> - __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
> - GFP_KERNEL);
> - if (tmp == NULL) {
> - rc = -ENOMEM;
> - goto parse_DFS_referrals_exit;
> - }
> - cifsConvertToUTF16((__le16 *) tmp, searchName,
> - PATH_MAX, nls_codepage, remap);
> - node->path_consumed = cifs_utf16_bytes(tmp,
> - le16_to_cpu(pSMBr->PathConsumed),
> - nls_codepage);
> - kfree(tmp);
> - } else
> - node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
> -
> - node->server_type = le16_to_cpu(ref->ServerType);
> - node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
> -
> - /* copy DfsPath */
> - temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
> - max_len = data_end - temp;
> - node->path_name = cifs_strndup_from_utf16(temp, max_len,
> - is_unicode, nls_codepage);
> - if (!node->path_name) {
> - rc = -ENOMEM;
> - goto parse_DFS_referrals_exit;
> - }
> -
> - /* copy link target UNC */
> - temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
> - max_len = data_end - temp;
> - node->node_name = cifs_strndup_from_utf16(temp, max_len,
> - is_unicode, nls_codepage);
> - if (!node->node_name) {
> - rc = -ENOMEM;
> - goto parse_DFS_referrals_exit;
> - }
> -
> - ref++;
> - }
> -
> -parse_DFS_referrals_exit:
> - if (rc) {
> - free_dfs_info_array(*target_nodes, *num_of_nodes);
> - *target_nodes = NULL;
> - *num_of_nodes = 0;
> - }
> - return rc;
> -}
> -
> int
> CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
> const char *search_name, struct dfs_info3_param **target_nodes,
> @@ -4993,9 +4882,11 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
> get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
>
> /* parse returned result into more usable form */
> - rc = parse_DFS_referrals(pSMBr, num_of_nodes,
> - target_nodes, nls_codepage, remap,
> - search_name);
> + rc = parse_dfs_referrals(&pSMBr->dfs_data,
> + le16_to_cpu(pSMBr->t2.DataCount),
> + num_of_nodes, target_nodes, nls_codepage,
> + remap, search_name,
> + pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
>
> GetDFSRefExit:
> cifs_buf_release(pSMB);
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index c672915..d3fb115 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -640,3 +640,108 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
> cifs_add_pending_open_locked(fid, tlink, open);
> spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
> }
> +
> +/* parses DFS refferal V3 structure
> + * caller is responsible for freeing target_nodes
> + * returns:
> + * - on success - 0
> + * - on failure - errno
> + */
> +int
> +parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
> + unsigned int *num_of_nodes,
> + struct dfs_info3_param **target_nodes,
> + const struct nls_table *nls_codepage, int remap,
> + const char *searchName, bool is_unicode)
> +{
> + int i, rc = 0;
> + char *data_end;
> + struct dfs_referral_level_3 *ref;
> +
> + *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
> +
> + if (*num_of_nodes < 1) {
> + cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
> + *num_of_nodes);
> + rc = -EINVAL;
> + goto parse_DFS_referrals_exit;
> + }
> +
> + ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
> + if (ref->VersionNumber != cpu_to_le16(3)) {
> + cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
> + le16_to_cpu(ref->VersionNumber));
> + rc = -EINVAL;
> + goto parse_DFS_referrals_exit;
> + }
> +
> + /* get the upper boundary of the resp buffer */
> + data_end = (char *)rsp + rsp_size;
> +
> + cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
> + *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
> +
> + *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
> + GFP_KERNEL);
> + if (*target_nodes == NULL) {
> + rc = -ENOMEM;
> + goto parse_DFS_referrals_exit;
> + }
> +
> + /* collect necessary data from referrals */
> + for (i = 0; i < *num_of_nodes; i++) {
> + char *temp;
> + int max_len;
> + struct dfs_info3_param *node = (*target_nodes)+i;
> +
> + node->flags = le32_to_cpu(rsp->DFSFlags);
> + if (is_unicode) {
> + __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
> + GFP_KERNEL);
> + if (tmp == NULL) {
> + rc = -ENOMEM;
> + goto parse_DFS_referrals_exit;
> + }
> + cifsConvertToUTF16((__le16 *) tmp, searchName,
> + PATH_MAX, nls_codepage, remap);
> + node->path_consumed = cifs_utf16_bytes(tmp,
> + le16_to_cpu(rsp->PathConsumed),
> + nls_codepage);
> + kfree(tmp);
> + } else
> + node->path_consumed = le16_to_cpu(rsp->PathConsumed);
> +
> + node->server_type = le16_to_cpu(ref->ServerType);
> + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
> +
> + /* copy DfsPath */
> + temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
> + max_len = data_end - temp;
> + node->path_name = cifs_strndup_from_utf16(temp, max_len,
> + is_unicode, nls_codepage);
> + if (!node->path_name) {
> + rc = -ENOMEM;
> + goto parse_DFS_referrals_exit;
> + }
> +
> + /* copy link target UNC */
> + temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
> + max_len = data_end - temp;
> + node->node_name = cifs_strndup_from_utf16(temp, max_len,
> + is_unicode, nls_codepage);
> + if (!node->node_name) {
> + rc = -ENOMEM;
> + goto parse_DFS_referrals_exit;
> + }
> +
> + ref++;
> + }
> +
> +parse_DFS_referrals_exit:
> + if (rc) {
> + free_dfs_info_array(*target_nodes, *num_of_nodes);
> + *target_nodes = NULL;
> + *num_of_nodes = 0;
> + }
> + return rc;
> +}
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Acked-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 2/7] CIFS: add build_path_from_dentry_optional_prefix()
[not found] ` <20170228184034.18771-3-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:35 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:35 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> this function does the same thing as add build_path_from_dentry() but
> takes a boolean parameter to decide whether or not to prefix the path
> with the tree name.
>
> we cannot rely on tcon->Flags & SMB_SHARE_IS_IN_DFS for SMB2 as smb2
> code never sets tcon->Flags but it sets tcon->share_flags and it seems
> the SMB_SHARE_IS_IN_DFS has different semantics in SMB2: the prefix
> shouldn't be added everytime it was in SMB1.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/cifs_dfs_ref.c | 4 +++-
> fs/cifs/cifsproto.h | 2 ++
> fs/cifs/dir.c | 13 ++++++++++++-
> 3 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
> index ec9dbbc..8a9ebfd 100644
> --- a/fs/cifs/cifs_dfs_ref.c
> +++ b/fs/cifs/cifs_dfs_ref.c
> @@ -302,7 +302,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
> * gives us the latter, so we must adjust the result.
> */
> mnt = ERR_PTR(-ENOMEM);
> - full_path = build_path_from_dentry(mntpt);
> +
> + /* always use tree name prefix */
> + full_path = build_path_from_dentry_optional_prefix(mntpt, true);
> if (full_path == NULL)
> goto cdda_exit;
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index c097830..9ee46c1 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -61,6 +61,8 @@ extern void exit_cifs_idmap(void);
> extern int init_cifs_spnego(void);
> extern void exit_cifs_spnego(void);
> extern char *build_path_from_dentry(struct dentry *);
> +extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
> + bool prefix);
> extern char *cifs_build_path_to_root(struct smb_vol *vol,
> struct cifs_sb_info *cifs_sb,
> struct cifs_tcon *tcon,
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index 2c227a9..56366e9 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -81,6 +81,17 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
> char *
> build_path_from_dentry(struct dentry *direntry)
> {
> + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
> + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
> + bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
> +
> + return build_path_from_dentry_optional_prefix(direntry,
> + prefix);
> +}
> +
> +char *
> +build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
> +{
> struct dentry *temp;
> int namelen;
> int dfsplen;
> @@ -92,7 +103,7 @@ build_path_from_dentry(struct dentry *direntry)
> unsigned seq;
>
> dirsep = CIFS_DIR_SEP(cifs_sb);
> - if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
> + if (prefix)
> dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
> else
> dfsplen = 0;
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Acked-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 3/7] CIFS: add use_ipc flag to SMB2_ioctl()
[not found] ` <20170228184034.18771-4-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:36 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:36 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> when set, use the session IPC tree id instead of the tid in the provided
> tcon.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/smb2file.c | 3 ++-
> fs/cifs/smb2ops.c | 23 ++++++++++++++++-------
> fs/cifs/smb2pdu.c | 17 +++++++++++++++--
> fs/cifs/smb2proto.h | 3 ++-
> 4 files changed, 35 insertions(+), 11 deletions(-)
>
> diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
> index b2aff0c..b4b1f03 100644
> --- a/fs/cifs/smb2file.c
> +++ b/fs/cifs/smb2file.c
> @@ -73,7 +73,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
> nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
> nr_ioctl_req.Reserved = 0;
> rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
> - fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true,
> + fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
> + true /* is_fsctl */, false /* use_ipc */,
> (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
> NULL, NULL /* no return info */);
> if (rc == -EOPNOTSUPP) {
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index a44b4db..02937cc 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -282,6 +282,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
>
> rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
> + false /* use_ipc */,
> NULL /* no data input */, 0 /* no data input */,
> (char **)&out_buf, &ret_data_len);
> if (rc != 0)
> @@ -571,6 +572,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
>
> rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
> FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
> + false /* use_ipc */,
> NULL, 0 /* no input */,
> (char **)&res_key, &ret_data_len);
>
> @@ -635,7 +637,8 @@ smb2_clone_range(const unsigned int xid,
> /* Request server copy to target from src identified by key */
> rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
> trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
> - true /* is_fsctl */, (char *)pcchunk,
> + true /* is_fsctl */, false /* use_ipc */,
> + (char *)pcchunk,
> sizeof(struct copychunk_ioctl), (char **)&retbuf,
> &ret_data_len);
> if (rc == 0) {
> @@ -787,7 +790,8 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
>
> rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
> cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
> - true /* is_fctl */, &setsparse, 1, NULL, NULL);
> + true /* is_fctl */, false /* use_ipc */,
> + &setsparse, 1, NULL, NULL);
> if (rc) {
> tcon->broken_sparse_sup = true;
> cifs_dbg(FYI, "set sparse rc = %d\n", rc);
> @@ -857,7 +861,8 @@ smb2_duplicate_extents(const unsigned int xid,
> rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
> trgtfile->fid.volatile_fid,
> FSCTL_DUPLICATE_EXTENTS_TO_FILE,
> - true /* is_fsctl */, (char *)&dup_ext_buf,
> + true /* is_fsctl */, false /* use_ipc */,
> + (char *)&dup_ext_buf,
> sizeof(struct duplicate_extents_to_file),
> NULL,
> &ret_data_len);
> @@ -891,7 +896,8 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
> return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
> cfile->fid.volatile_fid,
> FSCTL_SET_INTEGRITY_INFORMATION,
> - true /* is_fsctl */, (char *)&integr_info,
> + true /* is_fsctl */, false /* use_ipc */,
> + (char *)&integr_info,
> sizeof(struct fsctl_set_integrity_information_req),
> NULL,
> &ret_data_len);
> @@ -910,7 +916,8 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
> rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
> cfile->fid.volatile_fid,
> FSCTL_SRV_ENUMERATE_SNAPSHOTS,
> - true /* is_fsctl */, NULL, 0 /* no input data */,
> + true /* is_fsctl */, false /* use_ipc */,
> + NULL, 0 /* no input data */,
> (char **)&retbuf,
> &ret_data_len);
> cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
> @@ -1220,7 +1227,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
>
> rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
> cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
> - true /* is_fctl */, (char *)&fsctl_buf,
> + true /* is_fctl */, false /* use_ipc */,
> + (char *)&fsctl_buf,
> sizeof(struct file_zero_data_information), NULL, NULL);
> free_xid(xid);
> return rc;
> @@ -1254,7 +1262,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
>
> rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
> cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
> - true /* is_fctl */, (char *)&fsctl_buf,
> + true /* is_fctl */, false /* use_ipc */,
> + (char *)&fsctl_buf,
> sizeof(struct file_zero_data_information), NULL, NULL);
> free_xid(xid);
> return rc;
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index ad83b3d..8c4532d 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -620,6 +620,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
>
> rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
> + false /* use_ipc */,
> (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req),
> (char **)&pneg_rsp, &rsplen);
>
> @@ -1683,8 +1684,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> */
> int
> SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
> - u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data,
> - u32 indatalen, char **out_data, u32 *plen /* returned data len */)
> + u64 volatile_fid, u32 opcode, bool is_fsctl, bool use_ipc,
> + char *in_data, u32 indatalen,
> + char **out_data, u32 *plen /* returned data len */)
> {
> struct smb2_ioctl_req *req;
> struct smb2_ioctl_rsp *rsp;
> @@ -1721,6 +1723,16 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
> if (rc)
> return rc;
>
> + if (use_ipc) {
> + if (ses->ipc_tid == 0) {
> + cifs_small_buf_release(req);
> + return -ENOTCONN;
> + }
> +
> + cifs_dbg(FYI, "replacing tid 0x%x with IPC tid 0x%x\n",
> + req->hdr.sync_hdr.TreeId, ses->ipc_tid);
> + req->hdr.sync_hdr.TreeId = ses->ipc_tid;
> + }
> if (encryption_required(tcon))
> flags |= CIFS_TRANSFORM_REQ;
>
> @@ -1843,6 +1855,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
>
> rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
> FSCTL_SET_COMPRESSION, true /* is_fsctl */,
> + false /* use_ipc */,
> (char *)&fsctl_input /* data input */,
> 2 /* in data len */, &ret_data /* out data */, NULL);
>
> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
> index 85fc7a7..11d9f30 100644
> --- a/fs/cifs/smb2proto.h
> +++ b/fs/cifs/smb2proto.h
> @@ -121,7 +121,8 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
> struct smb2_err_rsp **err_buf);
> extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
> u64 persistent_fid, u64 volatile_fid, u32 opcode,
> - bool is_fsctl, char *in_data, u32 indatalen,
> + bool is_fsctl, bool use_ipc,
> + char *in_data, u32 indatalen,
> char **out_data, u32 *plen /* returned data len */);
> extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
> u64 persistent_file_id, u64 volatile_file_id);
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Reviewed-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 4/7] CIFS: let ses->ipc_tid hold smb2 TreeIds
[not found] ` <20170228184034.18771-5-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:36 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:36 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> the TreeId field went from 2 bytes in CIFS to 4 bytes in SMB2+. this
> commit updates the size of the ipc_tid field of a cifs_ses, which was
> still using 2 bytes.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/cifsglob.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 1a90bb3..af224cd 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -822,7 +822,7 @@ struct cifs_ses {
> int ses_count; /* reference counter */
> enum statusEnum status;
> unsigned overrideSecFlg; /* if non-zero override global sec flags */
> - __u16 ipc_tid; /* special tid for connection to IPC share */
> + __u32 ipc_tid; /* special tid for connection to IPC share */
> char *serverOS; /* name of operating system underlying server */
> char *serverNOS; /* name of network operating system of server */
> char *serverDomain; /* security realm of server */
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Reviewed-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 5/7] CIFS: set signing flag in SMB2+ TreeConnect if needed
[not found] ` <20170228184034.18771-6-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:37 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:37 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> cifs_enable_signing() already sets server->sign according to what the
> server requires/offers and what mount options allows/forbids, so use
> that.
>
> this is required for IPC tcon that connects to signing-required servers.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/smb2pdu.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index 8c4532d..2fd93ee 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -1168,8 +1168,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>
> /* since no tcon, smb2_init can not do this, so do here */
> req->hdr.sync_hdr.SessionId = ses->Suid;
> - /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
> - req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
> + if (ses->server->sign)
> + req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
> } else if (encryption_required(tcon))
> flags |= CIFS_TRANSFORM_REQ;
>
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Reviewed-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 6/7] CIFS: use DFS pathnames in SMB2+ Create requests
[not found] ` <20170228184034.18771-7-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:40 ` Pavel Shilovsky
0 siblings, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:40 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> When connected to a DFS capable share, the client must set the
> SMB2_FLAGS_DFS_OPERATIONS flag in the SMB2 header and use
> DFS path names: "<server>\<share>\<path>" *without* leading \\.
>
> Sources:
>
> [MS-SMB2] 3.2.5.5 Receiving an SMB2 TREE_CONNECT Response
>> TreeConnect.IsDfsShare MUST be set to TRUE, if the SMB2_SHARE_CAP_DFS
>> bit is set in the Capabilities field of the response.
>
> [MS-SMB2] 3.2.4.3 Application Requests Opening a File
>> If TreeConnect.IsDfsShare is TRUE, the SMB2_FLAGS_DFS_OPERATIONS flag
>> is set in the Flags field.
>
> [MS-SMB2] 2.2.13 SMB2 CREATE Request, NameOffset:
>> If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of the SMB2
>> header, the file name includes a prefix that will be processed during
>> DFS name normalization as specified in section 3.3.5.9. Otherwise, the
>> file name is relative to the share that is identified by the TreeId in
>> the SMB2 header.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/smb2pdu.c | 93 +++++++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 77 insertions(+), 16 deletions(-)
>
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index 2fd93ee..059da05 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -1528,6 +1528,48 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
> return 0;
> }
>
> +static int
> +alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
> + const char *treename, const __le16 *path)
> +{
> + int treename_len, path_len;
> + const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
> +
> + /*
> + * skip leading "\\"
> + */
> + treename_len = strlen(treename);
> + if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
> + return -EINVAL;
> +
> + treename += 2;
> + treename_len -= 2;
> +
> + path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
> +
> + /*
> + * make room for one path separator between the treename and
> + * path
> + */
> + *out_len = treename_len + 1 + path_len;
> +
> + /*
> + * final path needs to be null-terminated UTF16 with a
> + * size aligned to 8
> + */
> +
> + *out_size = roundup((*out_len+1)*2, 8);
> + *out_path = kzalloc(*out_size, GFP_KERNEL);
> + if (!*out_path)
> + return -ENOMEM;
> +
> + cifs_strtoUTF16(*out_path, treename, treename_len, load_nls_default());
> + UniStrcat(*out_path, sep);
> + UniStrcat(*out_path, path);
> +
> + return 0;
> +}
> +
> int
> SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> __u8 *oplock, struct smb2_file_all_info *buf,
> @@ -1576,30 +1618,49 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> req->ShareAccess = FILE_SHARE_ALL_LE;
> req->CreateDisposition = cpu_to_le32(oparms->disposition);
> req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
> - uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
> - /* do not count rfc1001 len field */
> - req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
>
> iov[0].iov_base = (char *)req;
> /* 4 for rfc1002 length field */
> iov[0].iov_len = get_rfc1002_length(req) + 4;
> -
> - /* MUST set path len (NameLength) to 0 opening root of share */
> - req->NameLength = cpu_to_le16(uni_path_len - 2);
> /* -1 since last byte is buf[0] which is sent below (path) */
> iov[0].iov_len--;
> - if (uni_path_len % 8 != 0) {
> - copy_size = uni_path_len / 8 * 8;
> - if (copy_size < uni_path_len)
> - copy_size += 8;
> -
> - copy_path = kzalloc(copy_size, GFP_KERNEL);
> - if (!copy_path)
> - return -ENOMEM;
> - memcpy((char *)copy_path, (const char *)path,
> - uni_path_len);
> +
> + req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
> +
> + /* [MS-SMB2] 2.2.13 NameOffset:
> + * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
> + * the SMB2 header, the file name includes a prefix that will
> + * be processed during DFS name normalization as specified in
> + * section 3.3.5.9. Otherwise, the file name is relative to
> + * the share that is identified by the TreeId in the SMB2
> + * header.
> + */
> + if (tcon->share_flags & SHI1005_FLAGS_DFS) {
> + int name_len;
> +
> + req->hdr.sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
> + rc = alloc_path_with_tree_prefix(©_path, ©_size,
> + &name_len,
> + tcon->treeName, path);
> + if (rc)
> + return rc;
> + req->NameLength = cpu_to_le16(name_len * 2);
> uni_path_len = copy_size;
> path = copy_path;
> + } else {
> + uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
> + /* MUST set path len (NameLength) to 0 opening root of share */
> + req->NameLength = cpu_to_le16(uni_path_len - 2);
> + if (uni_path_len % 8 != 0) {
> + copy_size = roundup(uni_path_len, 8);
> + copy_path = kzalloc(copy_size, GFP_KERNEL);
> + if (!copy_path)
> + return -ENOMEM;
> + memcpy((char *)copy_path, (const char *)path,
> + uni_path_len);
> + uni_path_len = copy_size;
> + path = copy_path;
> + }
> }
>
> iov[1].iov_len = uni_path_len;
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Acked-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+
[not found] ` <20170228184034.18771-8-aaptel-IBi9RG/b67k@public.gmane.org>
@ 2017-03-01 2:42 ` Pavel Shilovsky
2017-06-22 23:03 ` Pavel Shilovsky
1 sibling, 0 replies; 19+ messages in thread
From: Pavel Shilovsky @ 2017-03-01 2:42 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> in SMB2+ the get_dfs_refer operation uses a FSCTL. The request can be
> made on any Tree Connection according to the specs. Since Samba only
> accepted it on an IPC connection until recently, try that first.
>
> https://lists.samba.org/archive/samba-technical/2017-February/118859.html
>
> 3.2.4.20.3 Application Requests DFS Referral Information:
>> The client MUST search for an existing Session and TreeConnect to any
>> share on the server identified by ServerName for the user identified by
>> UserCredentials. If no Session and TreeConnect are found, the client
>> MUST establish a new Session and TreeConnect to IPC$ on the target
>> server as described in section 3.2.4.2 using the supplied ServerName and
>> UserCredentials.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/smb2ops.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> fs/cifs/smb2pdu.h | 8 +++++
> 2 files changed, 108 insertions(+)
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 02937cc..fcd524d 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -1104,6 +1104,102 @@ smb2_new_lease_key(struct cifs_fid *fid)
> generate_random_uuid(fid->lease_key);
> }
>
> +static int
> +smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
> + const char *search_name,
> + struct dfs_info3_param **target_nodes,
> + unsigned int *num_of_nodes,
> + const struct nls_table *nls_codepage, int remap)
> +{
> + int rc;
> + __le16 *utf16_path = NULL;
> + int utf16_path_len = 0;
> + struct cifs_tcon *tcon;
> + struct fsctl_get_dfs_referral_req *dfs_req = NULL;
> + struct get_dfs_referral_rsp *dfs_rsp = NULL;
> + u32 dfs_req_size = 0, dfs_rsp_size = 0;
> +
> + cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
> +
> + /*
> + * Use any tcon from the current session. Here, the first one.
> + */
> + spin_lock(&cifs_tcp_ses_lock);
> + tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, tcon_list);
> + if (tcon)
> + tcon->tc_count++;
> + spin_unlock(&cifs_tcp_ses_lock);
> +
> + if (!tcon) {
> + cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
> + ses);
> + rc = -ENOTCONN;
> + goto out;
> + }
> +
> + utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
> + &utf16_path_len,
> + nls_codepage, remap);
> + if (!utf16_path) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
> + dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
> + if (!dfs_req) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + /* Highest DFS referral version understood */
> + dfs_req->MaxReferralLevel = cpu_to_le16(DFS_VERSION);
> +
> + /* Path to resolve in an UTF-16 null-terminated string */
> + memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
> +
> + do {
> + /* try first with IPC */
> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> + FSCTL_DFS_GET_REFERRALS,
> + true /* is_fsctl */, true /* use_ipc */,
> + (char *)dfs_req, dfs_req_size,
> + (char **)&dfs_rsp, &dfs_rsp_size);
> + if (rc == -ENOTCONN) {
> + /* try with normal tcon */
> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> + FSCTL_DFS_GET_REFERRALS,
> + true /* is_fsctl */, false /*use_ipc*/,
> + (char *)dfs_req, dfs_req_size,
> + (char **)&dfs_rsp, &dfs_rsp_size);
> + }
> + } while (rc == -EAGAIN);
> +
> + if (rc) {
> + cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
> + goto out;
> + }
> +
> + rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
> + num_of_nodes, target_nodes,
> + nls_codepage, remap, search_name,
> + true /* is_unicode */);
> + if (rc) {
> + cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc);
> + goto out;
> + }
> +
> + out:
> + if (tcon) {
> + spin_lock(&cifs_tcp_ses_lock);
> + tcon->tc_count--;
> + spin_unlock(&cifs_tcp_ses_lock);
> + }
> + kfree(utf16_path);
> + kfree(dfs_req);
> + kfree(dfs_rsp);
> + return rc;
> +}
> #define SMB2_SYMLINK_STRUCT_SIZE \
> (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
>
> @@ -2263,6 +2359,7 @@ struct smb_version_operations smb20_operations = {
> .clone_range = smb2_clone_range,
> .wp_retry_size = smb2_wp_retry_size,
> .dir_needs_close = smb2_dir_needs_close,
> + .get_dfs_refer = smb2_get_dfs_refer,
> };
>
> struct smb_version_operations smb21_operations = {
> @@ -2344,6 +2441,7 @@ struct smb_version_operations smb21_operations = {
> .wp_retry_size = smb2_wp_retry_size,
> .dir_needs_close = smb2_dir_needs_close,
> .enum_snapshots = smb3_enum_snapshots,
> + .get_dfs_refer = smb2_get_dfs_refer,
> };
>
> struct smb_version_operations smb30_operations = {
> @@ -2435,6 +2533,7 @@ struct smb_version_operations smb30_operations = {
> .free_transform_rq = smb3_free_transform_rq,
> .is_transform_hdr = smb3_is_transform_hdr,
> .receive_transform = smb3_receive_transform,
> + .get_dfs_refer = smb2_get_dfs_refer,
> };
>
> #ifdef CONFIG_CIFS_SMB311
> @@ -2527,6 +2626,7 @@ struct smb_version_operations smb311_operations = {
> .free_transform_rq = smb3_free_transform_rq,
> .is_transform_hdr = smb3_is_transform_hdr,
> .receive_transform = smb3_receive_transform,
> + .get_dfs_refer = smb2_get_dfs_refer,
> };
> #endif /* CIFS_SMB311 */
>
> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
> index c03b252..18700fd 100644
> --- a/fs/cifs/smb2pdu.h
> +++ b/fs/cifs/smb2pdu.h
> @@ -695,6 +695,14 @@ struct fsctl_get_integrity_information_rsp {
> /* Integrity flags for above */
> #define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
>
> +/* See MS-DFSC 2.2.2 */
> +struct fsctl_get_dfs_referral_req {
> + __le16 MaxReferralLevel;
> + __u8 RequestFileName[];
> +} __packed;
> +
> +/* DFS response is struct get_dfs_refer_rsp */
> +
> /* See MS-SMB2 2.2.31.3 */
> struct network_resiliency_req {
> __le32 Timeout;
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Reviewed-by: Pavel Shilovsky <pshilov-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 0/7] Add support for DFS in SMB2+
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
` (6 preceding siblings ...)
2017-02-28 18:40 ` [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+ Aurelien Aptel
@ 2017-03-02 4:41 ` Steve French
7 siblings, 0 replies; 19+ messages in thread
From: Steve French @ 2017-03-02 4:41 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA
Merged v4 of this into cifs-2.6.git for-next
On Tue, Feb 28, 2017 at 12:40 PM, Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org> wrote:
> This series of patch tries to implement the get_dfs_refer operation
> for SMB2+.
>
> In SMB2+, DFS resolving is now done through an FSCTL (patch #7). The
> relevant Microsoft specifications for this are:
>
> MS-SMB2: 3.2.4.20 Application Requests an IO Control Code Operation
> MS-SMB2: 3.2.4.20.3 Application Requests DFS Referral Information
> MS-SMB2: 3.2.5.14 Receiving an SMB2 IOCTL Response
> MS-SMB2: 3.2.5.14.4 Handling a DFS Referral Information Response
>
> MS-DFSC: 2.2 Message Syntax (but really the whole document is useful)
>
> The DFS response payload however is identical. Patch #1 moves the
> DFS response parsing out of SMB1 code and makes it work on any version
> of SMB.
>
> DFS code has 2 "main" entry points: initial mounting and automount
> (when a DFS link is accessed/traversed).
>
> When automounting, cifs.ko calls build_path_from_dentry() which only
> makes treename-prefixed paths when the tcon has the
> SMB_IN_DFS_SHARE. This flag is checked in tcon->Flags which is never
> touched by SMB2 code as it sets tcon->share_flags on connexion.
>
> * CIFS requires to prefix all pathnames with the treename prefix when
> connected to a DFS server, so the current build_path_from_dentry()
> makes sense for CIFS.
> * For SMB2+ it seems only the Create request requires the treename
> prefix. Simply making the function check for both CIFS SMB2+ flag
> for DFS to add a prefix does not work as the server has different
> expectations about which packet can have/require a DFS pathname.
>
> Patch #2 adds build_path_from_dentry_optional_prefix() with an extra
> bool arg to decide to prefix or not. The automount code path always
> ask for it. Patch #6 modifies SMB2_open() to add the treename prefix
> to the given path if the server requires it.
>
> We try to use an IPC connection first for the DFS request. Patch #3
> adds a flag to SMB2_ioctl() to force the usage of ipc_tid. The SMB2
> get_dfs_refer operation tries with the flag set and fallback to a
> share connection if that doesn't work.
>
> Patch #4 updates the type of ipc_tid from u16 to u32 as that is what a
> Tid is in SMB2+. This is correct and really needed since in SMB2 Samba
> doesn't use sequential tree id but random ones in the 32bit space.
>
> As part of the mouting process a IPC tcon is made (I suspect we don't
> need it anymore in SMB3). This tcon doesn't respect the signing
> requirement. This is fixed by patch #5.
>
> Finally the SMB2+ implementation of the get_dfs_referral operation is
> added in all supported SMB versions in patch #7.
>
> I've sucessfuly tested this (v1.0 and v3.0) against a Windows Server
> 2016 DFS setup and a Samba DFS setup.
>
> Samba used to only accepts DFS referrals requests on an IPC connexion,
> which is in violation of the spec. A patch was sent on samba-technical
> and merged. It is not required anymore.
>
> https://lists.samba.org/archive/samba-technical/2017-February/118859.html
>
> Changes since v2:
>
> * add use_ipc flag to SMB2_open()
> * make smb2_get_dfs_refer() try IPC connections first
> * use first_entry_or_null() instead of first_entry() on the tcon list
> * protect tcon list access with spinlock
> * add inc/dec of the tcon reference number, protected by spinlock
>
> Aurelien Aptel (7):
> CIFS: move DFS response parsing out of SMB1 code
> CIFS: add build_path_from_dentry_optional_prefix()
> CIFS: add use_ipc flag to SMB2_ioctl()
> CIFS: let ses->ipc_tid hold smb2 TreeIds
> CIFS: set signing flag in SMB2+ TreeConnect if needed
> CIFS: use DFS pathnames in SMB2+ Create requests
> CIFS: implement get_dfs_refer for SMB2+
>
> fs/cifs/cifs_dfs_ref.c | 4 +-
> fs/cifs/cifsglob.h | 2 +-
> fs/cifs/cifspdu.h | 16 ++++---
> fs/cifs/cifsproto.h | 7 +++
> fs/cifs/cifssmb.c | 119 ++---------------------------------------------
> fs/cifs/dir.c | 13 +++++-
> fs/cifs/misc.c | 105 +++++++++++++++++++++++++++++++++++++++++
> fs/cifs/smb2file.c | 3 +-
> fs/cifs/smb2ops.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++---
> fs/cifs/smb2pdu.c | 114 +++++++++++++++++++++++++++++++++++++--------
> fs/cifs/smb2pdu.h | 8 ++++
> fs/cifs/smb2proto.h | 3 +-
> 12 files changed, 365 insertions(+), 152 deletions(-)
>
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Thanks,
Steve
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+
[not found] ` <20170228184034.18771-8-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:42 ` Pavel Shilovsky
@ 2017-06-22 23:03 ` Pavel Shilovsky
[not found] ` <CAKywueTx4b4+MDYeTm+jBsUZfmYe+Sa1HT9cUx-d4043hKxr+A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
1 sibling, 1 reply; 19+ messages in thread
From: Pavel Shilovsky @ 2017-06-22 23:03 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
> in SMB2+ the get_dfs_refer operation uses a FSCTL. The request can be
> made on any Tree Connection according to the specs. Since Samba only
> accepted it on an IPC connection until recently, try that first.
>
> https://lists.samba.org/archive/samba-technical/2017-February/118859.html
>
> 3.2.4.20.3 Application Requests DFS Referral Information:
>> The client MUST search for an existing Session and TreeConnect to any
>> share on the server identified by ServerName for the user identified by
>> UserCredentials. If no Session and TreeConnect are found, the client
>> MUST establish a new Session and TreeConnect to IPC$ on the target
>> server as described in section 3.2.4.2 using the supplied ServerName and
>> UserCredentials.
>
> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
> ---
> fs/cifs/smb2ops.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> fs/cifs/smb2pdu.h | 8 +++++
> 2 files changed, 108 insertions(+)
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 02937cc..fcd524d 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -1104,6 +1104,102 @@ smb2_new_lease_key(struct cifs_fid *fid)
> generate_random_uuid(fid->lease_key);
> }
>
> +static int
> +smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
> + const char *search_name,
> + struct dfs_info3_param **target_nodes,
> + unsigned int *num_of_nodes,
> + const struct nls_table *nls_codepage, int remap)
> +{
> + int rc;
> + __le16 *utf16_path = NULL;
> + int utf16_path_len = 0;
> + struct cifs_tcon *tcon;
> + struct fsctl_get_dfs_referral_req *dfs_req = NULL;
> + struct get_dfs_referral_rsp *dfs_rsp = NULL;
> + u32 dfs_req_size = 0, dfs_rsp_size = 0;
> +
> + cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
> +
> + /*
> + * Use any tcon from the current session. Here, the first one.
> + */
> + spin_lock(&cifs_tcp_ses_lock);
> + tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, tcon_list);
> + if (tcon)
> + tcon->tc_count++;
> + spin_unlock(&cifs_tcp_ses_lock);
> +
> + if (!tcon) {
> + cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
> + ses);
> + rc = -ENOTCONN;
> + goto out;
> + }
> +
> + utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
> + &utf16_path_len,
> + nls_codepage, remap);
> + if (!utf16_path) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
> + dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
> + if (!dfs_req) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + /* Highest DFS referral version understood */
> + dfs_req->MaxReferralLevel = cpu_to_le16(DFS_VERSION);
> +
> + /* Path to resolve in an UTF-16 null-terminated string */
> + memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
> +
> + do {
> + /* try first with IPC */
> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> + FSCTL_DFS_GET_REFERRALS,
> + true /* is_fsctl */, true /* use_ipc */,
> + (char *)dfs_req, dfs_req_size,
> + (char **)&dfs_rsp, &dfs_rsp_size);
> + if (rc == -ENOTCONN) {
> + /* try with normal tcon */
> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
> + FSCTL_DFS_GET_REFERRALS,
> + true /* is_fsctl */, false /*use_ipc*/,
> + (char *)dfs_req, dfs_req_size,
> + (char **)&dfs_rsp, &dfs_rsp_size);
> + }
> + } while (rc == -EAGAIN);
> +
> + if (rc) {
> + cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
> + goto out;
> + }
During the local testing with cthon and xfstests with DFS is being
involved I see a bunch of error messages like the one below:
CIFS VFS: ioctl error in smb2_get_dfs_refer rc=-2
Should we lower a debug level to FYI here?
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+
[not found] ` <CAKywueTx4b4+MDYeTm+jBsUZfmYe+Sa1HT9cUx-d4043hKxr+A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-06-22 23:05 ` Pavel Shilovsky
[not found] ` <CAKywueSy1Y1PNLHkRnDbxgc+Kf1qe_H65DPkWpX-=k=Enu-VUw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 19+ messages in thread
From: Pavel Shilovsky @ 2017-06-22 23:05 UTC (permalink / raw)
To: Aurelien Aptel; +Cc: linux-cifs
2017-06-22 16:03 GMT-07:00 Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> 2017-02-28 10:40 GMT-08:00 Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>:
>> in SMB2+ the get_dfs_refer operation uses a FSCTL. The request can be
>> made on any Tree Connection according to the specs. Since Samba only
>> accepted it on an IPC connection until recently, try that first.
>>
>> https://lists.samba.org/archive/samba-technical/2017-February/118859.html
>>
>> 3.2.4.20.3 Application Requests DFS Referral Information:
>>> The client MUST search for an existing Session and TreeConnect to any
>>> share on the server identified by ServerName for the user identified by
>>> UserCredentials. If no Session and TreeConnect are found, the client
>>> MUST establish a new Session and TreeConnect to IPC$ on the target
>>> server as described in section 3.2.4.2 using the supplied ServerName and
>>> UserCredentials.
>>
>> Signed-off-by: Aurelien Aptel <aaptel-IBi9RG/b67k@public.gmane.org>
>> ---
>> fs/cifs/smb2ops.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> fs/cifs/smb2pdu.h | 8 +++++
>> 2 files changed, 108 insertions(+)
>>
>> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
>> index 02937cc..fcd524d 100644
>> --- a/fs/cifs/smb2ops.c
>> +++ b/fs/cifs/smb2ops.c
>> @@ -1104,6 +1104,102 @@ smb2_new_lease_key(struct cifs_fid *fid)
>> generate_random_uuid(fid->lease_key);
>> }
>>
>> +static int
>> +smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
>> + const char *search_name,
>> + struct dfs_info3_param **target_nodes,
>> + unsigned int *num_of_nodes,
>> + const struct nls_table *nls_codepage, int remap)
>> +{
>> + int rc;
>> + __le16 *utf16_path = NULL;
>> + int utf16_path_len = 0;
>> + struct cifs_tcon *tcon;
>> + struct fsctl_get_dfs_referral_req *dfs_req = NULL;
>> + struct get_dfs_referral_rsp *dfs_rsp = NULL;
>> + u32 dfs_req_size = 0, dfs_rsp_size = 0;
>> +
>> + cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
>> +
>> + /*
>> + * Use any tcon from the current session. Here, the first one.
>> + */
>> + spin_lock(&cifs_tcp_ses_lock);
>> + tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, tcon_list);
>> + if (tcon)
>> + tcon->tc_count++;
>> + spin_unlock(&cifs_tcp_ses_lock);
>> +
>> + if (!tcon) {
>> + cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
>> + ses);
>> + rc = -ENOTCONN;
>> + goto out;
>> + }
>> +
>> + utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
>> + &utf16_path_len,
>> + nls_codepage, remap);
>> + if (!utf16_path) {
>> + rc = -ENOMEM;
>> + goto out;
>> + }
>> +
>> + dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
>> + dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
>> + if (!dfs_req) {
>> + rc = -ENOMEM;
>> + goto out;
>> + }
>> +
>> + /* Highest DFS referral version understood */
>> + dfs_req->MaxReferralLevel = cpu_to_le16(DFS_VERSION);
>> +
>> + /* Path to resolve in an UTF-16 null-terminated string */
>> + memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
>> +
>> + do {
>> + /* try first with IPC */
>> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
>> + FSCTL_DFS_GET_REFERRALS,
>> + true /* is_fsctl */, true /* use_ipc */,
>> + (char *)dfs_req, dfs_req_size,
>> + (char **)&dfs_rsp, &dfs_rsp_size);
>> + if (rc == -ENOTCONN) {
>> + /* try with normal tcon */
>> + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
>> + FSCTL_DFS_GET_REFERRALS,
>> + true /* is_fsctl */, false /*use_ipc*/,
>> + (char *)dfs_req, dfs_req_size,
>> + (char **)&dfs_rsp, &dfs_rsp_size);
>> + }
>> + } while (rc == -EAGAIN);
>> +
>> + if (rc) {
>> + cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
>> + goto out;
>> + }
>
> During the local testing with cthon and xfstests with DFS is being
^^^
Sorry, the above should be "without DFS being involved".
--
Best regards,
Pavel Shilovsky
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+
[not found] ` <CAKywueSy1Y1PNLHkRnDbxgc+Kf1qe_H65DPkWpX-=k=Enu-VUw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2017-06-23 9:19 ` Aurélien Aptel
0 siblings, 0 replies; 19+ messages in thread
From: Aurélien Aptel @ 2017-06-23 9:19 UTC (permalink / raw)
To: Pavel Shilovsky; +Cc: linux-cifs
Hi Pavel,
Pavel Shilovsky <piastryyy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:
>> Should we lower a debug level to FYI here?
Sounds good.
--
Aurélien Aptel / SUSE Labs Samba Team
GPG: 1839 CB5F 9F5B FB9B AA97 8C99 03C8 A49B 521B D5D3
SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2017-06-23 9:19 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-28 18:40 [PATCH v3 0/7] Add support for DFS in SMB2+ Aurelien Aptel
[not found] ` <20170228184034.18771-1-aaptel-IBi9RG/b67k@public.gmane.org>
2017-02-28 18:40 ` [PATCH v3 1/7] CIFS: move DFS response parsing out of SMB1 code Aurelien Aptel
[not found] ` <20170228184034.18771-2-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 1:58 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 2/7] CIFS: add build_path_from_dentry_optional_prefix() Aurelien Aptel
[not found] ` <20170228184034.18771-3-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:35 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 3/7] CIFS: add use_ipc flag to SMB2_ioctl() Aurelien Aptel
[not found] ` <20170228184034.18771-4-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:36 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 4/7] CIFS: let ses->ipc_tid hold smb2 TreeIds Aurelien Aptel
[not found] ` <20170228184034.18771-5-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:36 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 5/7] CIFS: set signing flag in SMB2+ TreeConnect if needed Aurelien Aptel
[not found] ` <20170228184034.18771-6-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:37 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 6/7] CIFS: use DFS pathnames in SMB2+ Create requests Aurelien Aptel
[not found] ` <20170228184034.18771-7-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:40 ` Pavel Shilovsky
2017-02-28 18:40 ` [PATCH v3 7/7] CIFS: implement get_dfs_refer for SMB2+ Aurelien Aptel
[not found] ` <20170228184034.18771-8-aaptel-IBi9RG/b67k@public.gmane.org>
2017-03-01 2:42 ` Pavel Shilovsky
2017-06-22 23:03 ` Pavel Shilovsky
[not found] ` <CAKywueTx4b4+MDYeTm+jBsUZfmYe+Sa1HT9cUx-d4043hKxr+A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-06-22 23:05 ` Pavel Shilovsky
[not found] ` <CAKywueSy1Y1PNLHkRnDbxgc+Kf1qe_H65DPkWpX-=k=Enu-VUw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-06-23 9:19 ` Aurélien Aptel
2017-03-02 4:41 ` [PATCH v3 0/7] Add support for DFS in SMB2+ Steve French
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.