summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/cifspdu.h2
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c24
-rw-r--r--fs/cifs/connect.c38
-rw-r--r--fs/cifs/misc.c12
-rw-r--r--fs/cifs/netmisc.c9
-rw-r--r--fs/cifs/transport.c4
8 files changed, 60 insertions, 33 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 661b45906d0..53517723802 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -4,7 +4,8 @@ Fix readdir caching when unlink removes file in current search buffer,
and this is followed by a rewind search to just before the deleted entry.
Do not attempt to set ctime unless atime and/or mtime change requested
(most servers throw it away anyway). Fix length check of received smbs
-to be more accurate.
+to be more accurate. Fix big endian problem with mapchars mount option,
+and with a field returned by statfs.
Version 1.36
------------
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 3fa37790bea..193f06eb43f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -697,7 +697,7 @@ typedef struct smb_com_openx_req {
__le32 EndOfFile;
__le32 Timeout;
__le32 Reserved;
- __u16 ByteCount; /* file name follows */
+ __le16 ByteCount; /* file name follows */
char fileName[1];
} OPENX_REQ;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0bace385e97..dc5a6a6ff2f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -56,6 +56,7 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb);
extern int is_size_safe_to_change(struct cifsInodeInfo *);
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
+extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType);
extern int cifs_inet_pton(int, char * source, void *dst);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index daf717e6b6e..52caac063a7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -779,7 +779,7 @@ OldOpenRetry:
/* BB FIXME END BB */
pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
- pSMB->OpenFunction = convert_disposition(openDisposition);
+ pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
count += name_len;
pSMB->hdr.smb_buf_length += count;
@@ -808,10 +808,12 @@ OldOpenRetry:
pfile_info->LastAccessTime = 0; /* BB fixme */
pfile_info->LastWriteTime = 0; /* BB fixme */
pfile_info->ChangeTime = 0; /* BB fixme */
- pfile_info->Attributes = pSMBr->FileAttributes;
+ pfile_info->Attributes =
+ cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
/* the file_info buf is endian converted by caller */
- pfile_info->AllocationSize = pSMBr->EndOfFile;
- pfile_info->EndOfFile = pSMBr->EndOfFile;
+ pfile_info->AllocationSize =
+ cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
+ pfile_info->EndOfFile = pfile_info->AllocationSize;
pfile_info->NumberOfLinks = cpu_to_le32(1);
}
}
@@ -2390,9 +2392,11 @@ QInfRetry:
cFYI(1, ("Send error in QueryInfo = %d", rc));
} else if (pFinfo) { /* decode response */
memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
- pFinfo->AllocationSize = (__le64) pSMBr->size;
- pFinfo->EndOfFile = (__le64) pSMBr->size;
- pFinfo->Attributes = (__le32) pSMBr->attr;
+ pFinfo->AllocationSize =
+ cpu_to_le64(le32_to_cpu(pSMBr->size));
+ pFinfo->EndOfFile = pFinfo->AllocationSize;
+ pFinfo->Attributes =
+ cpu_to_le32(le16_to_cpu(pSMBr->attr));
} else
rc = -EIO; /* bad buffer passed in */
@@ -3722,16 +3726,16 @@ QFSPosixRetry:
le64_to_cpu(response_data->TotalBlocks);
FSData->f_bfree =
le64_to_cpu(response_data->BlocksAvail);
- if(response_data->UserBlocksAvail == -1) {
+ if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
FSData->f_bavail = FSData->f_bfree;
} else {
FSData->f_bavail =
le64_to_cpu(response_data->UserBlocksAvail);
}
- if(response_data->TotalFileNodes != -1)
+ if(response_data->TotalFileNodes != cpu_to_le64(-1))
FSData->f_files =
le64_to_cpu(response_data->TotalFileNodes);
- if(response_data->FreeFileNodes != -1)
+ if(response_data->FreeFileNodes != cpu_to_le64(-1))
FSData->f_ffree =
le64_to_cpu(response_data->FreeFileNodes);
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 196976049c0..e27e5ad8b59 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -303,12 +303,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
byte_count += total_in_buf2;
BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
- byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
+ byte_count = pTargetSMB->smb_buf_length;
byte_count += total_in_buf2;
/* BB also add check that we are not beyond maximum buffer size */
- pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
+ pTargetSMB->smb_buf_length = byte_count;
if(remaining == total_in_buf2) {
cFYI(1,("found the last secondary response"));
@@ -333,7 +333,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
struct cifsSesInfo *ses;
struct task_struct *task_to_wake = NULL;
struct mid_q_entry *mid_entry;
- char *temp;
+ char temp;
int isLargeBuf = FALSE;
int isMultiRsp;
int reconnect;
@@ -435,22 +435,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
continue;
}
- /* the right amount was read from socket - 4 bytes */
+ /* The right amount was read from socket - 4 bytes */
+ /* so we can now interpret the length field */
+ /* the first byte big endian of the length field,
+ is actually not part of the length but the type
+ with the most common, zero, as regular data */
+ temp = *((char *) smb_buffer);
+
+ /* Note that FC 1001 length is big endian on the wire,
+ but we convert it here so it is always manipulated
+ as host byte order */
pdu_length = ntohl(smb_buffer->smb_buf_length);
- cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
+ smb_buffer->smb_buf_length = pdu_length;
+
+ cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
- temp = (char *) smb_buffer;
- if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
+ if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
continue;
- } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
+ } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
cFYI(1,("Good RFC 1002 session rsp"));
continue;
- } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+ } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/* we get this from Windows 98 instead of
an error on SMB negprot response */
cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
- temp[4]));
+ pdu_length));
if(server->tcpStatus == CifsNew) {
/* if nack on negprot (rather than
ret of smb negprot error) reconnecting
@@ -472,9 +482,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
wake_up(&server->response_q);
continue;
}
- } else if (temp[0] != (char) 0) {
+ } else if (temp != (char) 0) {
cERROR(1,("Unknown RFC 1002 frame"));
- cifs_dump_mem(" Received Data: ", temp, length);
+ cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
+ length);
cifs_reconnect(server);
csocket = server->ssocket;
continue;
@@ -609,7 +620,8 @@ multi_t2_fnd:
} else if ((is_valid_oplock_break(smb_buffer) == FALSE)
&& (isMultiRsp == FALSE)) {
cERROR(1, ("No task to wake, unknown frame rcvd!"));
- cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+ cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
+ sizeof(struct smb_hdr));
}
} /* end while !EXITING */
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 26b35b55f31..8a0edd695f8 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -419,7 +419,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
int
checkSMB(struct smb_hdr *smb, __u16 mid, int length)
{
- __u32 len = be32_to_cpu(smb->smb_buf_length);
+ __u32 len = smb->smb_buf_length;
cFYI(0,
("Entering checkSMB with Length: %x, smb_buf_length: %x ",
length, len));
@@ -448,9 +448,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
if (checkSMBhdr(smb, mid))
return 1;
- if ((4 + len != smbCalcSize(smb))
+ if ((4 + len != smbCalcSize_LE(smb))
|| (4 + len != (unsigned int)length)) {
- cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
+ cERROR(1, ("smbCalcSize %x ", smbCalcSize_LE(smb)));
cERROR(1,
("bad smb size detected. The Mid=%d", smb->Mid));
return 1;
@@ -672,6 +672,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
int i,j,charlen;
int len_remaining = maxlen;
char src_char;
+ __u16 temp;
if(!mapChars)
return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
@@ -708,13 +709,14 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
break;*/
default:
charlen = cp->char2uni(source+i,
- len_remaining, target+j);
+ len_remaining, &temp);
/* if no match, use question mark, which
at least in some cases servers as wild card */
if(charlen < 1) {
target[j] = cpu_to_le16(0x003f);
charlen = 1;
- }
+ } else
+ target[j] = cpu_to_le16(temp);
len_remaining -= charlen;
/* character may take more than one byte in the
the source string, but will take exactly two
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 32efa32774d..29e6efc5597 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -868,7 +868,14 @@ unsigned int
smbCalcSize(struct smb_hdr *ptr)
{
return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
- 2 /* size of the bcc field itself */ + BCC(ptr));
+ 2 /* size of the bcc field */ + BCC(ptr));
+}
+
+unsigned int
+smbCalcSize_LE(struct smb_hdr *ptr)
+{
+ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
}
/* The following are taken from fs/ntfs/util.c */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index d5e0c4018f9..9e8e85a8d18 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -414,7 +414,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
spin_unlock(&GlobalMid_Lock);
- receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
+ receive_len = midQ->resp_buf->smb_buf_length;
} else {
cERROR(1,("No response buffer"));
if(midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -665,7 +665,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
spin_unlock(&GlobalMid_Lock);
- receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
+ receive_len = midQ->resp_buf->smb_buf_length;
} else {
cERROR(1,("No response buffer"));
if(midQ->midState == MID_REQUEST_SUBMITTED) {