aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c169
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/link.c1
4 files changed, 80 insertions, 97 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 845b18e1abe..b9f5e935f82 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -146,8 +146,8 @@ extern int CIFSSMBUnixQPathInfo(const int xid,
extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
const unsigned char *searchName,
- unsigned char **targetUNCs,
- unsigned int *number_of_UNC_in_array,
+ struct dfs_info3_param **target_nodes,
+ unsigned int *number_of_nodes_in_array,
const struct nls_table *nls_codepage, int remap);
extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 9c04ad40455..fc297383cb0 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3870,8 +3870,8 @@ GetInodeNumOut:
int
CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
const unsigned char *searchName,
- unsigned char **targetUNCs,
- unsigned int *number_of_UNC_in_array,
+ struct dfs_info3_param **target_nodes,
+ unsigned int *num_of_nodes,
const struct nls_table *nls_codepage, int remap)
{
/* TRANS2_GET_DFS_REFERRAL */
@@ -3884,8 +3884,8 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
unsigned int i;
char *temp;
__u16 params, byte_count;
- *number_of_UNC_in_array = 0;
- *targetUNCs = NULL;
+ *num_of_nodes = 0;
+ *target_nodes = NULL;
cFYI(1, ("In GetDFSRefer the path %s", searchName));
if (ses == NULL)
@@ -3955,99 +3955,84 @@ getDFSRetry:
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in GetDFSRefer = %d", rc));
- } else { /* decode response */
-/* BB Add logic to parse referrals here */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- /* BB Also check if enough total bytes returned? */
- if (rc || (pSMBr->ByteCount < 17))
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
-
- cFYI(1,
- ("Decoding GetDFSRefer response BCC: %d Offset %d",
- pSMBr->ByteCount, data_offset));
- referrals =
- (struct dfs_referral_level_3 *)
- (8 /* sizeof start of data block */ +
- data_offset +
- (char *) &pSMBr->hdr.Protocol);
- cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
- "for referral one refer size: 0x%x srv "
- "type: 0x%x refer flags: 0x%x ttl: 0x%x",
- le16_to_cpu(pSMBr->NumberOfReferrals),
- le16_to_cpu(pSMBr->DFSFlags),
- le16_to_cpu(referrals->ReferralSize),
- le16_to_cpu(referrals->ServerType),
- le16_to_cpu(referrals->ReferralFlags),
- le16_to_cpu(referrals->TimeToLive)));
- /* BB This field is actually two bytes in from start of
- data block so we could do safety check that DataBlock
- begins at address of pSMBr->NumberOfReferrals */
- *number_of_UNC_in_array =
- le16_to_cpu(pSMBr->NumberOfReferrals);
-
- /* BB Fix below so can return more than one referral */
- if (*number_of_UNC_in_array > 1)
- *number_of_UNC_in_array = 1;
-
- /* get the length of the strings describing refs */
- name_len = 0;
- for (i = 0; i < *number_of_UNC_in_array; i++) {
- /* make sure that DfsPathOffset not past end */
- __u16 offset =
- le16_to_cpu(referrals->DfsPathOffset);
- if (offset > data_count) {
- /* if invalid referral, stop here and do
- not try to copy any more */
- *number_of_UNC_in_array = i;
- break;
- }
- temp = ((char *)referrals) + offset;
+ goto GetDFSRefExit;
+ }
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len += UniStrnlen((wchar_t *)temp,
- data_count);
- } else {
- name_len += strnlen(temp, data_count);
- }
- referrals++;
- /* BB add check that referral pointer does
- not fall off end PDU */
- }
- /* BB add check for name_len bigger than bcc */
- *targetUNCs =
- kmalloc(name_len+1+(*number_of_UNC_in_array),
- GFP_KERNEL);
- if (*targetUNCs == NULL) {
- rc = -ENOMEM;
- goto GetDFSRefExit;
+ /* BB Also check if enough total bytes returned? */
+ if (rc || (pSMBr->ByteCount < 17))
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
+ pSMBr->ByteCount, data_offset));
+ referrals =
+ (struct dfs_referral_level_3 *)
+ (8 /* sizeof start of data block */ +
+ data_offset +
+ (char *) &pSMBr->hdr.Protocol);
+ cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
+ "for referral one refer size: 0x%x srv "
+ "type: 0x%x refer flags: 0x%x ttl: 0x%x",
+ le16_to_cpu(pSMBr->NumberOfReferrals),
+ le16_to_cpu(pSMBr->DFSFlags),
+ le16_to_cpu(referrals->ReferralSize),
+ le16_to_cpu(referrals->ServerType),
+ le16_to_cpu(referrals->ReferralFlags),
+ le16_to_cpu(referrals->TimeToLive)));
+ /* BB This field is actually two bytes in from start of
+ data block so we could do safety check that DataBlock
+ begins at address of pSMBr->NumberOfReferrals */
+ *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
+
+ /* BB Fix below so can return more than one referral */
+ if (*num_of_nodes > 1)
+ *num_of_nodes = 1;
+
+ /* get the length of the strings describing refs */
+ name_len = 0;
+ for (i = 0; i < *num_of_nodes; i++) {
+ /* make sure that DfsPathOffset not past end */
+ __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+ if (offset > data_count) {
+ /* if invalid referral, stop here and do
+ not try to copy any more */
+ *num_of_nodes = i;
+ break;
}
- /* copy the ref strings */
- referrals = (struct dfs_referral_level_3 *)
- (8 /* sizeof data hdr */ + data_offset +
- (char *) &pSMBr->hdr.Protocol);
-
- for (i = 0; i < *number_of_UNC_in_array; i++) {
- temp = ((char *)referrals) +
- le16_to_cpu(referrals->DfsPathOffset);
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- cifs_strfromUCS_le(*targetUNCs,
- (__le16 *) temp,
- name_len,
- nls_codepage);
- } else {
- strncpy(*targetUNCs, temp, name_len);
- }
- /* BB update target_uncs pointers */
- referrals++;
+ temp = ((char *)referrals) + offset;
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len += UniStrnlen((wchar_t *)temp,
+ data_count);
+ } else {
+ name_len += strnlen(temp, data_count);
}
- temp = *targetUNCs;
- temp[name_len] = 0;
+ referrals++;
+ /* BB add check that referral pointer does
+ not fall off end PDU */
+ }
+ /* BB add check for name_len bigger than bcc */
+ *target_nodes =
+ kmalloc(name_len+1+(*num_of_nodes),
+ GFP_KERNEL);
+ if (*target_nodes == NULL) {
+ rc = -ENOMEM;
+ goto GetDFSRefExit;
}
+ referrals = (struct dfs_referral_level_3 *)
+ (8 /* sizeof data hdr */ + data_offset +
+ (char *) &pSMBr->hdr.Protocol);
+
+ for (i = 0; i < *num_of_nodes; i++) {
+ temp = ((char *)referrals) +
+ le16_to_cpu(referrals->DfsPathOffset);
+ /* BB update target_uncs pointers */
+ referrals++;
+ }
}
GetDFSRefExit:
if (pSMB)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d5747e30f1c..c397fcfd9f1 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1425,7 +1425,6 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
{
char *temp_unc;
int rc = 0;
- unsigned char *targetUNCs;
*pnum_referrals = 0;
*preferrals = NULL;
@@ -1448,7 +1447,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
kfree(temp_unc);
}
if (rc == 0)
- rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &targetUNCs,
+ rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
pnum_referrals, nls_codepage, remap);
/* BB map targetUNCs to dfs_info3 structures, here or
in CIFSGetDFSRefer BB */
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 316f9830ce3..63f644000ce 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -234,7 +234,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
- char *tmp_path = NULL;
char *tmpbuffer;
int len;
__u16 fid;