]> err.no Git - linux-2.6/blobdiff - fs/cifs/misc.c
Merge branch 'work'
[linux-2.6] / fs / cifs / misc.c
index fafbdbfa63a1382d0c98e2208bf27e1559692fa1..94baf6c8ecbda85946984cd2e4d524034cc94644 100644 (file)
@@ -98,14 +98,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
        atomic_dec(&sesInfoAllocCount);
        list_del(&buf_to_free->cifsSessionList);
        write_unlock(&GlobalSMBSeslock);
-       if (buf_to_free->serverOS)
-               kfree(buf_to_free->serverOS);
-       if (buf_to_free->serverDomain)
-               kfree(buf_to_free->serverDomain);
-       if (buf_to_free->serverNOS)
-               kfree(buf_to_free->serverNOS);
-       if (buf_to_free->password)
-               kfree(buf_to_free->password);
+       kfree(buf_to_free->serverOS);
+       kfree(buf_to_free->serverDomain);
+       kfree(buf_to_free->serverNOS);
+       kfree(buf_to_free->password);
        kfree(buf_to_free);
 }
 
@@ -144,8 +140,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
        atomic_dec(&tconInfoAllocCount);
        list_del(&buf_to_free->cifsConnectionList);
        write_unlock(&GlobalSMBSeslock);
-       if (buf_to_free->nativeFileSystem)
-               kfree(buf_to_free->nativeFileSystem);
+       kfree(buf_to_free->nativeFileSystem);
        kfree(buf_to_free);
 }
 
@@ -402,12 +397,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
                        if(smb->Command == SMB_COM_LOCKING_ANDX)
                                return 0;
                        else
-                               cERROR(1, ("Rcvd Request not response "));         
+                               cERROR(1, ("Rcvd Request not response"));         
                }
        } else { /* bad signature or mid */
                if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
                        cERROR(1,
-                              ("Bad protocol string signature header %x ",
+                              ("Bad protocol string signature header %x",
                                *(unsigned int *) smb->Protocol));
                if (mid != smb->Mid)
                        cERROR(1, ("Mids do not match"));
@@ -419,9 +414,10 @@ 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;
+       __u32 clc_len;  /* calculated length */
        cFYI(0,
-            ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
+            ("Entering checkSMB with Length: %x, smb_buf_length: %x",
              length, len));
        if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
            (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
@@ -440,23 +436,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
                        cERROR(1,
                               ("smb_buf_length greater than MaxBufSize"));
                cERROR(1,
-                      ("bad smb detected. Illegal length. The mid=%d",
+                      ("bad smb detected. Illegal length. mid=%d",
                        smb->Mid));
                return 1;
        }
 
        if (checkSMBhdr(smb, mid))
                return 1;
-
-       if ((4 + len != smbCalcSize(smb))
+       clc_len = smbCalcSize_LE(smb);
+       if ((4 + len != clc_len)
            || (4 + len != (unsigned int)length)) {
-               return 0;
-       } else {
-               cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
-               cERROR(1,
-                      ("bad smb size detected. The Mid=%d", smb->Mid));
-               return 1;
+               cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
+                               clc_len, 4 + len));
+               cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
+               /* Windows XP can return a few bytes too much, presumably
+               an illegal pad, at the end of byte range lock responses 
+               so we allow for that three byte pad, as long as actual
+               received length is as long or longer than calculated length */
+               /* We have now had to extend this more, since there is a 
+               case in which it needs to be bigger still to handle a
+               malformed response to transact2 findfirst from WinXP when
+               access denied is returned and thus bcc and wct are zero
+               but server says length is 0x21 bytes too long as if the server
+               forget to reset the smb rfc1001 length when it reset the
+               wct and bcc to minimum size and drop the t2 parms and data */
+               if((4+len > clc_len) && (len <= clc_len + 512))
+                       return 0;
+               else
+                       return 1;
        }
+       return 0;
 }
 int
 is_valid_oplock_break(struct smb_hdr *buf)
@@ -673,9 +682,10 @@ 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);
+               return cifs_strtoUCS(target, source, PATH_MAX, cp);
 
        for(i = 0, j = 0; i < maxlen; j++) {
                src_char = source[i];
@@ -709,13 +719,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