aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-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 661b45906d09..535177238020 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -4,7 +4,8 @@ Fix readdir caching when unlink removes file in current search buffer,
4and this is followed by a rewind search to just before the deleted entry. 4and this is followed by a rewind search to just before the deleted entry.
5Do not attempt to set ctime unless atime and/or mtime change requested 5Do not attempt to set ctime unless atime and/or mtime change requested
6(most servers throw it away anyway). Fix length check of received smbs 6(most servers throw it away anyway). Fix length check of received smbs
7to be more accurate. 7to be more accurate. Fix big endian problem with mapchars mount option,
8and with a field returned by statfs.
8 9
9Version 1.36 10Version 1.36
10------------ 11------------
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 3fa37790bea2..193f06eb43f9 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -697,7 +697,7 @@ typedef struct smb_com_openx_req {
697 __le32 EndOfFile; 697 __le32 EndOfFile;
698 __le32 Timeout; 698 __le32 Timeout;
699 __le32 Reserved; 699 __le32 Reserved;
700 __u16 ByteCount; /* file name follows */ 700 __le16 ByteCount; /* file name follows */
701 char fileName[1]; 701 char fileName[1];
702} OPENX_REQ; 702} OPENX_REQ;
703 703
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0bace385e97a..dc5a6a6ff2f9 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);
56extern int is_valid_oplock_break(struct smb_hdr *smb); 56extern int is_valid_oplock_break(struct smb_hdr *smb);
57extern int is_size_safe_to_change(struct cifsInodeInfo *); 57extern int is_size_safe_to_change(struct cifsInodeInfo *);
58extern unsigned int smbCalcSize(struct smb_hdr *ptr); 58extern unsigned int smbCalcSize(struct smb_hdr *ptr);
59extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
59extern int decode_negTokenInit(unsigned char *security_blob, int length, 60extern int decode_negTokenInit(unsigned char *security_blob, int length,
60 enum securityEnum *secType); 61 enum securityEnum *secType);
61extern int cifs_inet_pton(int, char * source, void *dst); 62extern int cifs_inet_pton(int, char * source, void *dst);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index daf717e6b6eb..52caac063a77 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -779,7 +779,7 @@ OldOpenRetry:
779 /* BB FIXME END BB */ 779 /* BB FIXME END BB */
780 780
781 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); 781 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
782 pSMB->OpenFunction = convert_disposition(openDisposition); 782 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
783 count += name_len; 783 count += name_len;
784 pSMB->hdr.smb_buf_length += count; 784 pSMB->hdr.smb_buf_length += count;
785 785
@@ -808,10 +808,12 @@ OldOpenRetry:
808 pfile_info->LastAccessTime = 0; /* BB fixme */ 808 pfile_info->LastAccessTime = 0; /* BB fixme */
809 pfile_info->LastWriteTime = 0; /* BB fixme */ 809 pfile_info->LastWriteTime = 0; /* BB fixme */
810 pfile_info->ChangeTime = 0; /* BB fixme */ 810 pfile_info->ChangeTime = 0; /* BB fixme */
811 pfile_info->Attributes = pSMBr->FileAttributes; 811 pfile_info->Attributes =
812 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
812 /* the file_info buf is endian converted by caller */ 813 /* the file_info buf is endian converted by caller */
813 pfile_info->AllocationSize = pSMBr->EndOfFile; 814 pfile_info->AllocationSize =
814 pfile_info->EndOfFile = pSMBr->EndOfFile; 815 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
816 pfile_info->EndOfFile = pfile_info->AllocationSize;
815 pfile_info->NumberOfLinks = cpu_to_le32(1); 817 pfile_info->NumberOfLinks = cpu_to_le32(1);
816 } 818 }
817 } 819 }
@@ -2390,9 +2392,11 @@ QInfRetry:
2390 cFYI(1, ("Send error in QueryInfo = %d", rc)); 2392 cFYI(1, ("Send error in QueryInfo = %d", rc));
2391 } else if (pFinfo) { /* decode response */ 2393 } else if (pFinfo) { /* decode response */
2392 memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); 2394 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2393 pFinfo->AllocationSize = (__le64) pSMBr->size; 2395 pFinfo->AllocationSize =
2394 pFinfo->EndOfFile = (__le64) pSMBr->size; 2396 cpu_to_le64(le32_to_cpu(pSMBr->size));
2395 pFinfo->Attributes = (__le32) pSMBr->attr; 2397 pFinfo->EndOfFile = pFinfo->AllocationSize;
2398 pFinfo->Attributes =
2399 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2396 } else 2400 } else
2397 rc = -EIO; /* bad buffer passed in */ 2401 rc = -EIO; /* bad buffer passed in */
2398 2402
@@ -3722,16 +3726,16 @@ QFSPosixRetry:
3722 le64_to_cpu(response_data->TotalBlocks); 3726 le64_to_cpu(response_data->TotalBlocks);
3723 FSData->f_bfree = 3727 FSData->f_bfree =
3724 le64_to_cpu(response_data->BlocksAvail); 3728 le64_to_cpu(response_data->BlocksAvail);
3725 if(response_data->UserBlocksAvail == -1) { 3729 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3726 FSData->f_bavail = FSData->f_bfree; 3730 FSData->f_bavail = FSData->f_bfree;
3727 } else { 3731 } else {
3728 FSData->f_bavail = 3732 FSData->f_bavail =
3729 le64_to_cpu(response_data->UserBlocksAvail); 3733 le64_to_cpu(response_data->UserBlocksAvail);
3730 } 3734 }
3731 if(response_data->TotalFileNodes != -1) 3735 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3732 FSData->f_files = 3736 FSData->f_files =
3733 le64_to_cpu(response_data->TotalFileNodes); 3737 le64_to_cpu(response_data->TotalFileNodes);
3734 if(response_data->FreeFileNodes != -1) 3738 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3735 FSData->f_ffree = 3739 FSData->f_ffree =
3736 le64_to_cpu(response_data->FreeFileNodes); 3740 le64_to_cpu(response_data->FreeFileNodes);
3737 } 3741 }
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 196976049c00..e27e5ad8b591 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)
303 byte_count += total_in_buf2; 303 byte_count += total_in_buf2;
304 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); 304 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
305 305
306 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); 306 byte_count = pTargetSMB->smb_buf_length;
307 byte_count += total_in_buf2; 307 byte_count += total_in_buf2;
308 308
309 /* BB also add check that we are not beyond maximum buffer size */ 309 /* BB also add check that we are not beyond maximum buffer size */
310 310
311 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); 311 pTargetSMB->smb_buf_length = byte_count;
312 312
313 if(remaining == total_in_buf2) { 313 if(remaining == total_in_buf2) {
314 cFYI(1,("found the last secondary response")); 314 cFYI(1,("found the last secondary response"));
@@ -333,7 +333,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
333 struct cifsSesInfo *ses; 333 struct cifsSesInfo *ses;
334 struct task_struct *task_to_wake = NULL; 334 struct task_struct *task_to_wake = NULL;
335 struct mid_q_entry *mid_entry; 335 struct mid_q_entry *mid_entry;
336 char *temp; 336 char temp;
337 int isLargeBuf = FALSE; 337 int isLargeBuf = FALSE;
338 int isMultiRsp; 338 int isMultiRsp;
339 int reconnect; 339 int reconnect;
@@ -435,22 +435,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
435 continue; 435 continue;
436 } 436 }
437 437
438 /* the right amount was read from socket - 4 bytes */ 438 /* The right amount was read from socket - 4 bytes */
439 /* so we can now interpret the length field */
439 440
441 /* the first byte big endian of the length field,
442 is actually not part of the length but the type
443 with the most common, zero, as regular data */
444 temp = *((char *) smb_buffer);
445
446 /* Note that FC 1001 length is big endian on the wire,
447 but we convert it here so it is always manipulated
448 as host byte order */
440 pdu_length = ntohl(smb_buffer->smb_buf_length); 449 pdu_length = ntohl(smb_buffer->smb_buf_length);
441 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); 450 smb_buffer->smb_buf_length = pdu_length;
451
452 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
442 453
443 temp = (char *) smb_buffer; 454 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
444 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
445 continue; 455 continue;
446 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { 456 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
447 cFYI(1,("Good RFC 1002 session rsp")); 457 cFYI(1,("Good RFC 1002 session rsp"));
448 continue; 458 continue;
449 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { 459 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
450 /* we get this from Windows 98 instead of 460 /* we get this from Windows 98 instead of
451 an error on SMB negprot response */ 461 an error on SMB negprot response */
452 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", 462 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
453 temp[4])); 463 pdu_length));
454 if(server->tcpStatus == CifsNew) { 464 if(server->tcpStatus == CifsNew) {
455 /* if nack on negprot (rather than 465 /* if nack on negprot (rather than
456 ret of smb negprot error) reconnecting 466 ret of smb negprot error) reconnecting
@@ -472,9 +482,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
472 wake_up(&server->response_q); 482 wake_up(&server->response_q);
473 continue; 483 continue;
474 } 484 }
475 } else if (temp[0] != (char) 0) { 485 } else if (temp != (char) 0) {
476 cERROR(1,("Unknown RFC 1002 frame")); 486 cERROR(1,("Unknown RFC 1002 frame"));
477 cifs_dump_mem(" Received Data: ", temp, length); 487 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
488 length);
478 cifs_reconnect(server); 489 cifs_reconnect(server);
479 csocket = server->ssocket; 490 csocket = server->ssocket;
480 continue; 491 continue;
@@ -609,7 +620,8 @@ multi_t2_fnd:
609 } else if ((is_valid_oplock_break(smb_buffer) == FALSE) 620 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
610 && (isMultiRsp == FALSE)) { 621 && (isMultiRsp == FALSE)) {
611 cERROR(1, ("No task to wake, unknown frame rcvd!")); 622 cERROR(1, ("No task to wake, unknown frame rcvd!"));
612 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); 623 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
624 sizeof(struct smb_hdr));
613 } 625 }
614 } /* end while !EXITING */ 626 } /* end while !EXITING */
615 627
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 26b35b55f31b..8a0edd695f84 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -419,7 +419,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
419int 419int
420checkSMB(struct smb_hdr *smb, __u16 mid, int length) 420checkSMB(struct smb_hdr *smb, __u16 mid, int length)
421{ 421{
422 __u32 len = be32_to_cpu(smb->smb_buf_length); 422 __u32 len = smb->smb_buf_length;
423 cFYI(0, 423 cFYI(0,
424 ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 424 ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
425 length, len)); 425 length, len));
@@ -448,9 +448,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
448 if (checkSMBhdr(smb, mid)) 448 if (checkSMBhdr(smb, mid))
449 return 1; 449 return 1;
450 450
451 if ((4 + len != smbCalcSize(smb)) 451 if ((4 + len != smbCalcSize_LE(smb))
452 || (4 + len != (unsigned int)length)) { 452 || (4 + len != (unsigned int)length)) {
453 cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); 453 cERROR(1, ("smbCalcSize %x ", smbCalcSize_LE(smb)));
454 cERROR(1, 454 cERROR(1,
455 ("bad smb size detected. The Mid=%d", smb->Mid)); 455 ("bad smb size detected. The Mid=%d", smb->Mid));
456 return 1; 456 return 1;
@@ -672,6 +672,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
672 int i,j,charlen; 672 int i,j,charlen;
673 int len_remaining = maxlen; 673 int len_remaining = maxlen;
674 char src_char; 674 char src_char;
675 __u16 temp;
675 676
676 if(!mapChars) 677 if(!mapChars)
677 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); 678 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
@@ -708,13 +709,14 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
708 break;*/ 709 break;*/
709 default: 710 default:
710 charlen = cp->char2uni(source+i, 711 charlen = cp->char2uni(source+i,
711 len_remaining, target+j); 712 len_remaining, &temp);
712 /* if no match, use question mark, which 713 /* if no match, use question mark, which
713 at least in some cases servers as wild card */ 714 at least in some cases servers as wild card */
714 if(charlen < 1) { 715 if(charlen < 1) {
715 target[j] = cpu_to_le16(0x003f); 716 target[j] = cpu_to_le16(0x003f);
716 charlen = 1; 717 charlen = 1;
717 } 718 } else
719 target[j] = cpu_to_le16(temp);
718 len_remaining -= charlen; 720 len_remaining -= charlen;
719 /* character may take more than one byte in the 721 /* character may take more than one byte in the
720 the source string, but will take exactly two 722 the source string, but will take exactly two
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 32efa32774d2..29e6efc5597c 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -868,7 +868,14 @@ unsigned int
868smbCalcSize(struct smb_hdr *ptr) 868smbCalcSize(struct smb_hdr *ptr)
869{ 869{
870 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + 870 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
871 2 /* size of the bcc field itself */ + BCC(ptr)); 871 2 /* size of the bcc field */ + BCC(ptr));
872}
873
874unsigned int
875smbCalcSize_LE(struct smb_hdr *ptr)
876{
877 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
878 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
872} 879}
873 880
874/* The following are taken from fs/ntfs/util.c */ 881/* The following are taken from fs/ntfs/util.c */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index d5e0c4018f92..9e8e85a8d186 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -414,7 +414,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
414 spin_lock(&GlobalMid_Lock); 414 spin_lock(&GlobalMid_Lock);
415 if (midQ->resp_buf) { 415 if (midQ->resp_buf) {
416 spin_unlock(&GlobalMid_Lock); 416 spin_unlock(&GlobalMid_Lock);
417 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf); 417 receive_len = midQ->resp_buf->smb_buf_length;
418 } else { 418 } else {
419 cERROR(1,("No response buffer")); 419 cERROR(1,("No response buffer"));
420 if(midQ->midState == MID_REQUEST_SUBMITTED) { 420 if(midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -665,7 +665,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
665 spin_lock(&GlobalMid_Lock); 665 spin_lock(&GlobalMid_Lock);
666 if (midQ->resp_buf) { 666 if (midQ->resp_buf) {
667 spin_unlock(&GlobalMid_Lock); 667 spin_unlock(&GlobalMid_Lock);
668 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf); 668 receive_len = midQ->resp_buf->smb_buf_length;
669 } else { 669 } else {
670 cERROR(1,("No response buffer")); 670 cERROR(1,("No response buffer"));
671 if(midQ->midState == MID_REQUEST_SUBMITTED) { 671 if(midQ->midState == MID_REQUEST_SUBMITTED) {