Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netsmb Fix detection of SMB capabilities according to th...



details:   https://anonhg.NetBSD.org/src/rev/f01928c3c249
branches:  trunk
changeset: 748270:f01928c3c249
user:      tron <tron%NetBSD.org@localhost>
date:      Sun Oct 18 22:53:36 2009 +0000

description:
Fix detection of SMB capabilities according to the CIFS spec:
1.) SMB_CAP_LARGE_FILES advertises support for 64-bit file offsets.
2.) SMB_CAP_LARGE_READX and SMB_CAP_LARGE_WRITEX advertise support for
    large reads and writes (larger than 64KB).
The code previously only used SMB_CAP_LARGE_READX and SMB_CAP_LARGE_WRITEX
which is not correct and doesn't work for the Apple Time Capsule which
only supports SMB_CAP_LARGE_FILES. With these changes SMBFS can copy a
5GB to a Time Capsule and read it back without problems.

Thanks a lot to Allen Briggs for pointing out the broke assumptions
and explaining the CIFS spec to me. This fixes PR kern/42175.

diffstat:

 sys/netsmb/smb_smb.c |  49 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 42 insertions(+), 7 deletions(-)

diffs (106 lines):

diff -r 9543ed4f2b5c -r f01928c3c249 sys/netsmb/smb_smb.c
--- a/sys/netsmb/smb_smb.c      Sun Oct 18 21:58:37 2009 +0000
+++ b/sys/netsmb/smb_smb.c      Sun Oct 18 22:53:36 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: smb_smb.c,v 1.30 2009/03/18 16:00:24 cegger Exp $      */
+/*     $NetBSD: smb_smb.c,v 1.31 2009/10/18 22:53:36 tron Exp $        */
 
 /*
  * Copyright (c) 2000-2001 Boris Popov
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.30 2009/03/18 16:00:24 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.31 2009/10/18 22:53:36 tron Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -594,6 +594,22 @@
        u_int16_t residhi, residlo, off, doff;
        u_int32_t resid;
 
+       if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) &&
+           uio->uio_offset >= (1LL << 32)) {
+               /* Cannot read at/beyond 4G */
+               return (EFBIG);
+       }
+
+       if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX)) {
+               size_t blksz;
+
+               blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64;
+               if (blksz > 0xffff)
+                       blksz = 0xffff;
+
+               *len = min(blksz, *len);
+       }
+
        error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
        if (error)
                return error;
@@ -674,8 +690,26 @@
        u_int8_t wc;
        u_int16_t resid;
 
+       if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) &&
+           uio->uio_offset >= (1LL << 32)) {
+               /* Cannot write at/beyond 4G */
+               return (EFBIG);
+       }
+
+       if (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX) {
+               *len = min(SSTOVC(ssp)->vc_wxmax, *len);
+       } else {
+               size_t blksz;
+
+               blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64;
+               if (blksz > 0xffff)
+                       blksz = 0xffff;
+
+               *len = min(blksz, *len);
+       }
+
        error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
-       if (error)
+       if (error != 0)
                return (error);
        smb_rq_getrequest(rqp, &mbp);
        smb_rq_wstart(rqp);
@@ -687,7 +721,6 @@
        mb_put_uint32le(mbp, 0);        /* MBZ (timeout) */
        mb_put_uint16le(mbp, 0);        /* !write-thru */
        mb_put_uint16le(mbp, 0);
-       *len = min(SSTOVC(ssp)->vc_wxmax, *len);
        mb_put_uint16le(mbp, *len >> 16);
        mb_put_uint16le(mbp, *len);
        mb_put_uint16le(mbp, 64);       /* data offset from header start */
@@ -785,7 +818,8 @@
 {
        size_t tsize, len, resid;
        int error = 0;
-       int rx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_READX);
+       bool rx = (SMB_CAPS(SSTOVC(ssp)) &
+                  (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_READX)) != 0;
 
        resid = 0;      /* XXX gcc */
 
@@ -866,7 +900,8 @@
 {
        int error = 0;
        size_t len, tsize, resid;
-       int wx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX);
+       bool wx = (SMB_CAPS(SSTOVC(ssp)) &
+                  (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_WRITEX)) != 0;
 
        resid = 0;      /* XXX gcc */
 
@@ -877,7 +912,7 @@
                    error = smb_smb_writex(ssp, fid, &len, &resid, uio, scred);
                else
                    error = smb_smb_write(ssp, fid, &len, &resid, uio, scred);
-               if (error)
+               if (error != 0)
                        break;
                if (resid < len) {
                        error = EIO;



Home | Main Index | Thread Index | Old Index