public void DurableHandleV1_WithLeaseV1_WithoutHandleCaching()
        {
            /// 1. Client requests a durable handle with LeaseV1 context, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState.
            /// 2. Durable Handle is not granted.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            fileName = "DurableHandleV1_WithLeaseV1_WithoutHandleCaching" + Guid.NewGuid() + ".txt";
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);

            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState.");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);
            Guid leaseKey = Guid.NewGuid();

            // SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState
            LeaseStateValues            leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
            FILEID                      fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequest
                {
                    DurableRequest = Guid.Empty,
                },
                new Smb2CreateRequestLease
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                // Durable Handle should not be granted.
                CheckCreateContextResponsesNotExist(serverCreateContexts, new DefaultDurableHandleResponseChecker(BaseTestSite));
            });

            clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection);
            clientBeforeDisconnection.LogOff();
            clientBeforeDisconnection.Disconnect();
        }
        protected override void TestInitialize()
        {
            base.TestInitialize();
            client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            fileName     = "FileLevelTrim_" + Guid.NewGuid() + ".txt";
            uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
        }
        private void Negative_AlternativeChannel_NicRedundantOnServer(DialectRevision[] requestDialect, DialectRevision expectedDialect)
        {
            string contentWrite;
            string contentRead;
            uint   treeId;
            FILEID fileId;

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);
            // According to TD, server must support signing when it supports multichannel.
            // 3.3.5.5   Receiving an SMB2 SESSION_SETUP Request
            // 4. If Connection.Dialect belongs to the SMB 3.x dialect family, IsMultiChannelCapable is TRUE, and the SMB2_SESSION_FLAG_BINDING bit is
            //    set in the Flags field of the request, the server MUST perform the following:
            //    If the SMB2_FLAGS_SIGNED bit is not set in the Flags field in the header, the server MUST fail the request with error STATUS_INVALID_PARAMETER.
            TestConfig.CheckSigning();
            #endregion

            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Assert.IsTrue(
                clientIps.Count > 0,
                "Client should have at least one IP address");
            BaseTestSite.Assert.IsTrue(
                serverIps.Count > 1,
                "Server should have more than one IP address");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            WriteFromMainChannel(
                requestDialect,
                expectedDialect,
                serverIps[0],
                clientIps[0],
                contentWrite,
                true,
                out treeId,
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to read content from file from alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[1].ToString());
            ReadFromAlternativeChannel(
                requestDialect,
                expectedDialect,
                serverIps[1],
                clientIps[0],
                (uint)contentWrite.Length,
                treeId,
                fileId,
                out contentRead);
        }
        private void PrepareFileForTrimming(out uint treeId, out FILEID fileId)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_FILE_LEVEL_TRIM);
            #endregion

            string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            string fileName     = GetTestFileName(uncSharePath);
            string contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            smb2Functionalclient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            uint status = smb2Functionalclient.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "CREATE should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
            });

            status = smb2Functionalclient.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            status = smb2Functionalclient.TreeConnect(uncSharePath, out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            status = smb2Functionalclient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);

            status = smb2Functionalclient.Write(treeId, fileId, contentWrite);

            status = smb2Functionalclient.Close(treeId, fileId);

            status = smb2Functionalclient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);
        }
        public void MultipleChannel_MultiChannelOnSameNic()
        {
            #region Normal
            string contentWrite;
            string contentRead;
            uint   treeId;
            FILEID fileId;

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);
            TestConfig.CheckSigning();
            #endregion

            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Assert.IsTrue(
                clientIps.Count > 0,
                "Client should have at least one IP address");
            BaseTestSite.Assert.IsTrue(
                serverIps.Count > 0,
                "Server should have more than one IP address");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            WriteFromMainChannel(
                serverIps[0],
                clientIps[0],
                contentWrite,
                false,
                out treeId,
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to read content from file from alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            ReadFromAlternativeChannel(
                serverIps[0],
                clientIps[0],
                (uint)contentWrite.Length,
                treeId,
                fileId,
                out contentRead);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Verify the contents read from alternative channel are the same as the one written by main channel.");
            BaseTestSite.Assert.IsTrue(
                contentWrite.Equals(contentRead),
                "Content read should be identical to content written.");
            #endregion
        }
        protected override void TestInitialize()
        {
            base.TestInitialize();

            clientGuid           = Guid.NewGuid();
            clientBeforeFailover = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientAfterFailover  = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            accessIpList = Dns.GetHostAddresses(TestConfig.ClusteredFileServerName);
            uncSharePath = Smb2Utility.GetUncPath(TestConfig.ClusteredFileServerName, TestConfig.ClusteredFileShare);
            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            fileName     = GetTestFileName(uncSharePath);
        }
        protected override void TestInitialize()
        {
            base.TestInitialize();

            clientGuid           = Guid.NewGuid();
            clientBeforeFailover = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientAfterFailover  = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            accessIpList = Dns.GetHostEntry(TestConfig.ClusteredFileServerName).AddressList;
            uncSharePath = Smb2Utility.GetUncPath(TestConfig.ClusteredFileServerName, TestConfig.ClusteredFileShare);
            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            fileName     = string.Format("{0}_{1}.txt", CurrentTestCaseName, Guid.NewGuid());
        }
Example #8
0
        protected override void TestInitialize()
        {
            base.TestInitialize();

            clientForInitialOpen = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientForReOpen      = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            appInstanceId = Guid.NewGuid();
            contentWrite  = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            fileName     = GetTestFileName(uncSharePath);
        }
        public void BVT_DuplicateExtentsToFile()
        {
            // Check the platform and ReFS file system.
            // Prepare
            // Create a file
            uint   treeId;
            FILEID srcFileId;
            string fileName    = "DuplicateExtentsToFile_" + Guid.NewGuid() + ".txt";
            int    clusterSize = TestConfig.VolumnClusterSize;
            string content     = Smb2Utility.CreateRandomString(clusterSize * 2);

            NewTestFile(smb2Functionalclient, fileName, content, out treeId, out srcFileId);
            long sourceFileOffset = 0;
            long targetFileOffset = clusterSize * 1024;
            long byteCount        = clusterSize * 1024;

            smb2Functionalclient.DuplicateExtentsToFile(
                treeId,
                srcFileId,
                sourceFileOffset,
                targetFileOffset,
                byteCount,
                checker: (Packet_Header header, IOCTL_Response response) =>
            {
                if (header.Status == Smb2Status.STATUS_INVALID_DEVICE_REQUEST)
                {
                    // check if the server advertises the FILE_SUPPROTS_BLOCK_REFCOUNTING flag for a given open.
                    bool res = FSInfo_Query_FileFsAttributeInformation_IsSupported(smb2Functionalclient, treeId, srcFileId, FileSystemAttributes_Values.FILE_SUPPORTS_BLOCK_REFCOUNTING);
                    BaseTestSite.Assert.AreEqual(false, res,
                                                 "If the server adverties the FILE_SUPPORTS_BLOCK_REFCOUNTING flag for a given Open, " +
                                                 "the server must support the FSCTL_DUPLICATE_EXTENTS_TO_FILE command, " +
                                                 "as specified in [MS-FSA] section 2.1.5.9.4.");
                }
                else if (header.Status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "The server supports FSCTL_DUPLICATE_EXTENTS_TO_FILE, and response with STATUS_SUCCESS.");
                }
                else if (header.Status == Smb2Status.STATUS_MEDIA_WRITE_PROTECTED)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "If Open.File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                }
                else
                {
                    BaseTestSite.Log.Add(LogEntryKind.Warning, "Unexpected Response: {0}", Smb2Status.GetStatusCode(header.Status));
                }
            });

            // Check the file content.

            // Clean.
        }
Example #10
0
        private void FileOperation(OplockFileOperation fileOperation, string fileName)
        {
            Site.Log.Add(LogEntryKind.Debug, "File operation on same file from another client");

            Smb2FunctionalClient clientForAnotherOpen = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);

            clientForAnotherOpen.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic1IPAddress);

            clientForAnotherOpen.Negotiate(new DialectRevision[] { negotiatedDialect }, testConfig.IsSMB1NegotiateEnabled);

            clientForAnotherOpen.SessionSetup(
                testConfig.DefaultSecurityPackage,
                server,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            uint treeIdForAnotherOpen;

            clientForAnotherOpen.TreeConnect(
                uncSharePath,
                out treeIdForAnotherOpen);

            FILEID fileIdForAnotherOpen;

            Smb2CreateContextResponse[] serverCreateContexts;

            clientForAnotherOpen.Create(
                treeIdForAnotherOpen,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdForAnotherOpen,
                out serverCreateContexts);

            if (fileOperation == OplockFileOperation.WriteFromAnotherOpen)
            {
                string writeContent = Smb2Utility.CreateRandomString(1);

                clientForAnotherOpen.Write(treeIdForAnotherOpen, fileIdForAnotherOpen, writeContent);
            }

            usedTestClients.Push(clientForAnotherOpen);
        }
        private void PrepareTestFile()
        {
            uint treeId;
            Smb2FunctionalClient client = InitializeClient(testConfig.ScaleOutFileServerIP1, out treeId);

            // Initialize file name
            fileName = "ConflictModel_" + Guid.NewGuid() + ".txt";
            FILEID fileId;
            Smb2CreateContextResponse[] contexts;
            client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out contexts);
            client.Write(treeId, fileId, Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB));
            client.Close(treeId, fileId);
            client.LogOff();
            client.Disconnect();
        }
        public void ReadConfig(out ReplayServerConfig c)
        {
            writeContent = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);

            c = new ReplayServerConfig
            {
                MaxSmbVersionSupported      = ModelUtility.GetModelDialectRevision(testConfig.MaxSmbVersionSupported),
                IsDirectoryLeasingSupported = testConfig.IsDirectoryLeasingSupported,
                IsLeasingSupported          = testConfig.IsLeasingSupported,
                IsPersistentHandleSupported = testConfig.IsPersistentHandlesSupported,
                TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS = Boolean.Parse(testConfig.GetProperty("ShareTypeInclude_STYPE_CLUSTER_SOFS")),
                Platform = testConfig.Platform,
            };

            replayConfig = c;

            testConfig.CheckDialect(DialectRevision.Smb30);

            Site.Log.Add(LogEntryKind.Debug, c.ToString());
        }
        protected override void TestInitialize()
        {
            base.TestInitialize();

            ReadIpAddressesFromTestConfig(out clientIps, out serverIps);
            BaseTestSite.Assert.IsTrue(
                clientIps.Count > 1,
                "Client should have more than one IP address");
            BaseTestSite.Assert.IsTrue(
                serverIps.Count > 1,
                "Server should have more than one IP address");

            mainChannelClient        = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            alternativeChannelClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            clientGuid    = Guid.NewGuid();
            uncSharePath  = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            fileName      = GetTestFileName(uncSharePath);
            testDirectory = CreateTestDirectory(uncSharePath);
            contentWrite  = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
        }
        private void TestAsymmetricShare(DialectRevision requestMaxDialect, string serverName, bool isAsymmetricShare)
        {
            int  ret        = 0;
            uint callId     = 0;
            Guid clientGuid = Guid.NewGuid();
            WITNESS_INTERFACE_INFO registerInterface;
            string shareName = isAsymmetricShare ? TestConfig.AsymmetricShare : TestConfig.BasicFileShare;

            #region Get the file server to access it through SMB2
            IPAddress currentAccessIp = SWNTestUtility.GetCurrentAccessIP(serverName);
            BaseTestSite.Assert.IsNotNull(currentAccessIp, "IP address of the file server should NOT be empty");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Got the IP {0} to access the file server", currentAccessIp.ToString());
            #endregion

            #region Connect to the asymmetric share
            uncSharePath = Smb2Utility.GetUncPath(serverName, shareName);
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            testDirectory = CreateTestDirectory(uncSharePath);
            string file = string.Format(@"{0}\{1}", testDirectory, Guid.NewGuid().ToString());

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP");
            smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);
            smb2Client.ConnectToServerOverTCP(currentAccessIp);
            smb2Client.Negotiate(
                Smb2Utility.GetDialects(requestMaxDialect),
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed.");
                BaseTestSite.Assert.AreEqual(
                    requestMaxDialect,
                    response.DialectRevision,
                    "The server is expected to use dialect {0}. Actual dialect is {1}",
                    requestMaxDialect,
                    response.DialectRevision);
            });
            smb2Client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                serverName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            uint treeId = 0;
            Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request to the {0} on the {1}", shareName, serverName);
            DoUntilSucceed(
                () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { shareCapabilities = response.Capabilities; }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            if (requestMaxDialect == DialectRevision.Smb302 && isAsymmetricShare)
            {
                BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC),
                                           "The capabilities of the share should contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities);
            }
            else
            {
                BaseTestSite.Assert.IsFalse(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC),
                                            "The capabilities of the share should not contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities);

                #region Disconnect current SMB2 connection
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion
                return;
            }

            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            Guid createGuid = Guid.NewGuid();
            Guid leaseKey   = Guid.NewGuid();
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file.");
            smb2Client.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
            smb2Client.Write(treeId, fileId, content);

            string readContent;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file.");
            smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent);
            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "Content read should be identical to that written.");
            #endregion

            #region Get register interface
            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIp,
                                                           TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                           TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, serverName), TestConfig.FailoverTimeout,
                           "Retry BindServer until succeed within timeout span");

            WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST();
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrGetInterfaceList.");
            DoUntilSucceed(() =>
            {
                ret = swnClientForInterface.WitnessrGetInterfaceList(out interfaceList);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrGetInterfaceList returns with result code = 0x{0:x8}", ret);
                return(SWNTestUtility.VerifyInterfaceList(interfaceList, TestConfig.Platform));
            }, TestConfig.FailoverTimeout, "Retry to call WitnessrGetInterfaceList until succeed within timeout span");

            swnClientForInterface.SwnUnbind(TestConfig.Timeout);

            SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface);

            #endregion

            #region Get SHARE_MOVE_NOTIFICATION
            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForWitness,
                                                           (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6),
                                                           TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                           TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, serverName), TestConfig.FailoverTimeout,
                           "Retry BindServer until succeed within timeout span");

            string clientName = TestConfig.WitnessClientName;

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", serverName);
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIp.ToString());
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrRegisterEx.");
            ret = swnClientForWitness.WitnessrRegisterEx(SwnVersion.SWN_VERSION_2,
                                                         serverName,
                                                         shareName,
                                                         currentAccessIp.ToString(),
                                                         clientName,
                                                         WitnessrRegisterExFlagsValue.WITNESS_REGISTER_IP_NOTIFICATION,
                                                         120,
                                                         out pContext);
            BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegisterEx returns with result code = 0x{0:x8}", ret);

            BaseTestSite.Assert.IsNotNull(pContext, "Expect pContext is not null.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrAsyncNotify.");
            callId = swnClientForWitness.WitnessrAsyncNotify(pContext);
            BaseTestSite.Assert.AreNotEqual <uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId);

            // NOTICE
            // This comment is for current Windows Cluster test environment.
            // Current test environment has only two nodes and both they are optimum nodes.
            // So whatever the server name is, SHARE_MOVE_NOTIFICATION notification will be recieved.
            // The configuration items 'OptimumNodeOfAsymmetricShare' and 'NonOptimumNodeOfAsymmetricShare' are assigned the same default value.
            // The code in if block will be executed all the time.
            if (serverName == TestConfig.NonOptimumNodeOfAsymmetricShare)
            {
                #region Expect that SHARE_MOVE_NOTIFICATION notification will be received  when the client connects to the asymmetric share on the non-optimum share
                RESP_ASYNC_NOTIFY respNotify;
                ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrAsyncNotify returns with result code = 0x{0:x8}", ret);
                SWNTestUtility.PrintNotification(respNotify);
                SWNTestUtility.VerifyClientMoveShareMoveAndIpChange(respNotify, SwnMessageType.SHARE_MOVE_NOTIFICATION, (uint)SwnIPAddrInfoFlags.IPADDR_V4, TestConfig.Platform);

                #region Get the new IpAddr
                IPADDR_INFO_LIST ipAddrInfoList;
                SwnUtility.ParseIPAddrInfoList(respNotify, out ipAddrInfoList);
                currentAccessIp = (ipAddrInfoList.IPAddrList[0].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(ipAddrInfoList.IPAddrList[0].IPV4) : SWNTestUtility.ConvertIPV6(ipAddrInfoList.IPAddrList[0].IPV6);
                #endregion

                #region Unregister SWN Witness
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister.");
                ret = swnClientForWitness.WitnessrUnRegister(pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
                pContext = IntPtr.Zero;
                swnClientForWitness.SwnUnbind(TestConfig.Timeout);
                #endregion

                #region Disconnect current SMB2 connection
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT.");
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion
                #endregion
            }
            else
            {
                #region Expect that no SHARE_MOVE_NOTIFICATION notification will be received when the client connects to the asymmetric share on the optimum share
                bool isNotificationReceived = false;
                try
                {
                    RESP_ASYNC_NOTIFY respNotify;
                    ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
                    isNotificationReceived = true;
                }
                catch (TimeoutException)
                {
                    isNotificationReceived = false;
                }

                #region Disconnect current SMB2 connection
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion

                #region Unregister SWN Witness
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister.");
                ret = swnClientForWitness.WitnessrUnRegister(pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
                pContext = IntPtr.Zero;
                swnClientForWitness.SwnUnbind(TestConfig.Timeout);
                #endregion

                BaseTestSite.Assert.IsFalse(isNotificationReceived, "Expect that no notification will be received when the client has connected to asymmetric share on the optimum node.");
                #endregion

                return;
            }
            #endregion

            #region Connect to the share on the optimum node
            smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Got the IP {0} to access the file server", currentAccessIp.ToString());

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP");
            smb2Client.ConnectToServerOverTCP(currentAccessIp);
            smb2Client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: Guid.NewGuid(),
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed.");
            });
            smb2Client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                serverName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends TREE_CONNECT and wait for a response until timeout.");
            DoUntilSucceed(
                () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file.");
            smb2Client.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
            smb2Client.Write(treeId, fileId, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file.");
            smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent);
            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "Content read should be identical to that written.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT.");
            smb2Client.TreeDisconnect(treeId);
            smb2Client.LogOff();
            smb2Client.Disconnect();
            #endregion
        }
        /// <summary>
        /// Do operation to the file from the second client
        /// </summary>
        private void RequestFromSecondClient(RequestType requestFromSecondClient)
        {
            uint status = 0;
            Smb2CreateContextResponse[] contexts;
            switch (requestFromSecondClient)
            {
                case RequestType.ExclusiveLock:
                    // If the open is not created before, create here.
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    // If open is created successfully, then do the specified file operation.
                    // Otherwise, return the status to Model.
                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Lock(
                            treeId2,
                            0,
                            fileId2,
                            new LOCK_ELEMENT[]
                            {
                                new LOCK_ELEMENT
                                {
                                    Offset = 0,
                                    Length = (ulong)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                                    Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY
                                }
                            },
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Lease:
                    if (!testConfig.IsLeasingSupported)
                    {
                        // skip this case if leasing is not supported
                        Site.Assert.Inconclusive("This test case is applicable only when leasing is supported.");
                    }
                    status = secondClient.Create(
                        treeId2,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId2,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                        new Smb2CreateContextRequest[]
                        {
                            new Smb2CreateRequestLease
                            {
                                LeaseKey = Guid.NewGuid(),
                                LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING
                            }
                        },
                        createDisposition: CreateDisposition_Values.FILE_OPEN,
                        checker: (header, response) => { });
                    HandleConflictResult(status);
                    break;
                case RequestType.Delete:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_DELETE_ON_CLOSE | CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Close(treeId2, fileId2, checker: (responseHeader, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Write:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Write(
                            treeId2,
                            fileId2,
                            Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB),
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Read:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        byte[] data;
                        status = secondClient.Read(
                            treeId2,
                            fileId2,
                            0,
                            (uint)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                            out data,
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Do operation to the file from the first client
        /// </summary>
        private void RequestFromFirstClient(RequestType requestFromFirstClient)
        {
            Smb2CreateContextResponse[] contexts;
            switch (requestFromFirstClient)
            {
                case RequestType.ExclusiveLock:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    firstClient.Lock(
                        treeId1,
                        0,
                        fileId1,
                        new LOCK_ELEMENT[]
                        {
                            new LOCK_ELEMENT
                            {
                                Offset = 0,
                                Length = DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                                Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY
                            }
                        });
                    break;
                case RequestType.Lease:
                    if (!testConfig.IsLeasingSupported)
                    {
                        // skip this case if leasing is not supported
                        Site.Assert.Inconclusive("This test case is applicable only when leasing is supported.");
                    }
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                        new Smb2CreateContextRequest[]
                        {
                            new Smb2CreateRequestLease
                            {
                                LeaseKey = Guid.NewGuid(),
                                // [MS-SMB2] 3.3.5.9.8 
                                // If Connection.Dialect belongs to the SMB 3.x dialect family, TreeConnect.Share.Type includes STYPE_CLUSTER_SOFS, 
                                // and if LeaseState includes SMB2_LEASE_READ_CACHING, the server MUST set LeaseState to SMB2_LEASE_READ_CACHING, 
                                // otherwise set LeaseState to SMB2_LEASE_NONE.
                                // The share.type includes STYPE_CLUSTER_SOFS, so only READ_CACHING could be granted even the client applied for other lease.
                                // So the client only applies READ_CACHING here.
                                LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING
                            }
                        });
                    break;
                case RequestType.UncommitedDelete:
                case RequestType.Delete:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_DELETE_ON_CLOSE | CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);

                    // Close to delete the file
                    firstClient.Close(treeId1, fileId1);
                    break;
                case RequestType.Write:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    firstClient.Write(treeId1, fileId1, Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB));
                    break;
                case RequestType.Read:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    byte[] data;
                    firstClient.Read(treeId1, fileId1, 0, (uint)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024, out data);
                    break;
                default:
                    break;
            }
        }
        public void MultipleChannel_SecondChannelSessionSetupFailAtFirstTime()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);
            #endregion

            string contentWrite;
            string contentRead;
            uint   treeId;
            FILEID fileId;

            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Assert.IsTrue(
                clientIps.Count > 0,
                "Client should have at least one IP address");
            BaseTestSite.Assert.IsTrue(
                serverIps.Count > 0,
                "Server should have more than one IP address");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            WriteFromMainChannel(
                serverIps[0],
                clientIps[0],
                contentWrite,
                false,
                out treeId,
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Set up alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());

            alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIps[1], clientIps[1]);
            alternativeChannelClient.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                TestConfig.CheckNegotiateDialect(DialectRevision.Smb311, response);
                if (Smb2Utility.IsSmb3xFamily(DialectRevision.Smb311))
                {
                    TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response);
                }
            });

            status = alternativeChannelClient.AlternativeChannelSessionSetup(
                mainChannelClient,
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken,
                checker: (header, response) => { },
                invalidToken: true);

            BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_INVALID_PARAMETER, status,
                                         "The first SessionSetup from alternative channel should return STATUS_INVALID_PARAMETER since the token in buffer field is set to an invalid value.");

            status = alternativeChannelClient.AlternativeChannelSessionSetup(
                mainChannelClient,
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken,
                checker: (header, response) => { });
            BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "The second SessionSetup from alternative channel should succeed");

            contentRead = "";
            status      = alternativeChannelClient.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead);

            // Read should succeed.
            // If Read response returns STATUS_ACCESS_DEINIED, it means signingkey used by server is wrong, and so that the PreauthIntegrityHashValue (which is used to generate the signingkey) calculated by server is wrong.
            // It is very possible that server uses the first failed session setup request/response (alternative channel) to calculate PreauthIntegrityHashValue, which is wrong.
            BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Read from the alternative channel should succeed");

            alternativeChannelClient.Close(treeId, fileId);
            alternativeChannelClient.TreeDisconnect(treeId);
            alternativeChannelClient.LogOff();

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Verify the contents read from alternative channel are the same as the one written by main channel.");
            BaseTestSite.Assert.IsTrue(
                contentWrite.Equals(contentRead),
                "Content read should be identical to content written.");
        }
        public void FileOperationRequest(
            ReplayModelSwitchChannelType switchChannelType,
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelRequestCommand requestCommand,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isReplay,
            ReplayModelRequestCommandParameters requestCommandParameters)
        {
            if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                testConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            }

            uint status = Smb2Status.STATUS_SUCCESS;
            Smb2FunctionalClient client = null;

            #region Switch channel
            switch (switchChannelType)
            {
            case ReplayModelSwitchChannelType.MainChannel:
                if (smb2ClientMainChannel == null)
                {
                    InitializeMainChannel(
                        maxSmbVersionClientSupported,
                        clientGuidMainChannel,
                        ReplayModelShareType.NonCAShare,
                        out treeIdMainChannel);

                    #region Create
                    Smb2CreateContextResponse[] serverCreateContexts = null;

                    status = smb2ClientMainChannel.Create(
                        treeIdMainChannel,
                        fileNameMainChannel,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileIdMainChannel,
                        out serverCreateContexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                        null,
                        shareAccess: ShareAccess_Values.NONE);
                    #endregion
                }
                client = smb2ClientMainChannel;
                break;

            case ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                client = smb2ClientAlternativeChannel;
                break;

            case ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                smb2ClientMainChannel.Disconnect();
                smb2ClientMainChannel = null;
                client = smb2ClientAlternativeChannel;
                break;

            case ReplayModelSwitchChannelType.MainChannelWithAlternativeChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                client = smb2ClientMainChannel;
                break;

            default:
                Site.Assume.Fail("Unknown ReplayModelSwitchChannelType {0}.", switchChannelType);
                break;
            }
            #endregion

            #region Prepare data for read
            if (switchChannelType == ReplayModelSwitchChannelType.MainChannel && !prepared && requestCommand == ReplayModelRequestCommand.Read)
            {
                status = smb2ClientMainChannel.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    writeContent);
            }
            #endregion

            FillChannelSequence(client, channelSequence);

            if (requestCommand == ReplayModelRequestCommand.Write)
            {
                #region Write
                status = client.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? writeContent : Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb),
                    checker: (header, response) =>
                {
                },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.SetInfo)
            {
                #region SetInfo
                if (requestCommandParameters == ReplayModelRequestCommandParameters.AlternativeParameters)
                {
                    endOfFileInformation.EndOfFile = 512;
                }
                byte[] buffer = TypeMarshal.ToBytes <FileEndOfFileInformation>(endOfFileInformation);

                status = client.SetFileAttributes(
                    treeIdMainChannel,
                    (byte)FileInformationClasses.FileEndOfFileInformation,
                    fileIdMainChannel,
                    buffer,
                    checker: (header, response) =>
                {
                },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                #region IOCtl
                Packet_Header  ioCtlHeader;
                IOCTL_Response ioCtlResponse;
                byte[]         inputInResponse;
                byte[]         outputInResponse;
                status = client.ResiliencyRequest(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    (uint)(requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? 0 : 2000),
                    (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)),
                    out ioCtlHeader,
                    out ioCtlResponse,
                    out inputInResponse,
                    out outputInResponse,
                    checker: (header, response) =>
                {
                    // do nothing, skip the exception
                }
                    );
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.Read)
            {
                #region Read
                string data;
                status = client.Read(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    0,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? (uint)testConfig.WriteBufferLengthInKb * 1024 : 512,
                    out data,
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }

            FileOperationResponse((ModelSmb2Status)status, replayConfig);
        }
        public void BVT_CopyOffload()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep,
                                 "1. Create a file with specified length {0} as the source of offload copy.",
                                 TestConfig.WriteBufferLengthInKb * 1024);
            string content  = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            string fileName = Guid.NewGuid().ToString();
            uint   treeId;
            FILEID fileIdSrc;

            PrepareTestFile(fileName, content, out treeId, out fileIdSrc);

            BaseTestSite.Log.Add(LogEntryKind.TestStep,
                                 "2. Client sends IOCTL request with FSCTL_OFFLOAD_READ to ask server to generate the token of the content for offload copy.");
            STORAGE_OFFLOAD_TOKEN token;
            ulong fileOffsetToRead = 0;                                              //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes
            ulong copyLengthToRead = (ulong)TestConfig.WriteBufferLengthInKb * 1024; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes
            ulong transferLength;

            // Request hardware to generate a token that represents a range of file to be copied
            client.OffloadRead(
                treeId,
                fileIdSrc,
                fileOffsetToRead,
                copyLengthToRead,
                out transferLength,
                out token);

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Transfer length during OFFLOAD_READ is {0}", transferLength);
            BaseTestSite.Assert.AreEqual(copyLengthToRead, transferLength,
                                         "Transfer length {0} should be equal to copy length {1}", transferLength, copyLengthToRead);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3. Create another file as the destination of offload copy.");
            FILEID fileIdDest;

            Smb2CreateContextResponse[] serverCreateContexts;
            client.Create(
                treeId,
                Guid.NewGuid().ToString(),
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdDest,
                out serverCreateContexts);

            // The destination file of CopyOffload Write should be equal to or larger than the size of original file
            client.Write(treeId, fileIdDest, Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb));
            client.Flush(treeId, fileIdDest);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "4. Client sends IOCTL request with FSCTL_OFFLOAD_WRITE to ask server to copy the content from source to destination.");
            ulong fileOffsetToWrite = 0;              //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes
            ulong copyLengthToWrite = transferLength; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes
            ulong transferOffset    = 0;              //TransferOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes

            // Request hardware to write a range of file which is represented by the generated token
            // and length/offset to another place (a different file or different offset of the same file)
            client.OffloadWrite(
                treeId,
                fileIdDest,
                fileOffsetToWrite,
                copyLengthToWrite,
                transferOffset,
                token);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "5. Compare the content of section 1 with the content of section 2.");
            string readContent;

            // Read the content that was just offload copied
            client.Read(
                treeId,
                fileIdDest,
                fileOffsetToWrite,
                (uint)copyLengthToWrite,
                out readContent);

            BaseTestSite.Assert.IsTrue(
                readContent.Equals(content),
                "File content read should equal to original");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "6. Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
            client.Close(treeId, fileIdSrc);
            client.Close(treeId, fileIdDest);
            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        public void DurableHandleV2_Reconnect_WithoutPersistence()
        {
            /// 1. Client requests a durable handle V2 without persistent flag
            /// 2. Lose connection by disabling NIC
            /// 3. Client reconnects the durable handle V2 without persistent flag.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE);
            #endregion

            string content    = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            Guid   clientGuid = Guid.NewGuid();
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
            fileName = "DurableHandleV2_Reconnect_WithoutPersistence" + Guid.NewGuid() + ".txt";

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);

            Guid                        createGuid = Guid.NewGuid();
            Guid                        leaseKey   = Guid.NewGuid();
            LeaseStateValues            leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
            FILEID                      fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                },
                new Smb2CreateRequestLeaseV2
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue));
            });

            clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            #endregion

            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the durable handle");

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnectV2
                {
                    CreateGuid = createGuid,
                    FileId     = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                },
                new Smb2CreateRequestLeaseV2
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE);

            string readContent;
            clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent);

            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "The written content is expected to be equal to read content.");
            #endregion

            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
        }
        public void BVT_PersistentHandle_Reconnect()
        {
            /// 1. Client requests a persistent handle
            /// 2. Client disconnects from the server
            /// 3. Client reconnects the persistent handle, and expects success.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2);
            #endregion

            string content    = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            Guid   clientGuid = Guid.NewGuid();
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName);
            fileName = "BVT_PersistentHandle_Reconnect_" + Guid.NewGuid() + ".txt";

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a persistent handle");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdBeforeDisconnection, null);

            Guid   createGuid = Guid.NewGuid();
            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            status = clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                    Flags      = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT, uint.MaxValue));
            });

            status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            #endregion

            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the persistent handle");

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdAfterDisconnection, clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            status = clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnectV2
                {
                    CreateGuid = createGuid,
                    Flags      = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                    FileId     = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE);

            string readContent;
            status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent);

            BaseTestSite.Assert.IsTrue(
                readContent.Equals(content),
                "The written content should equal to read content.");
            #endregion

            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
        }
        private void DurableHandleV1_Reconnect_WithoutLogoff(bool isPreviousSessionIdSet)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb2002);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
            fileName = "DurableHandleV1_Reconnect_WithoutLogoff" + Guid.NewGuid() + ".txt";

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);

            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequest
                {
                    DurableRequest = Guid.Empty
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleResponseChecker(BaseTestSite));
            });

            clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            #endregion

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the durable handle");

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb21, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert,
                    out treeIdAfterDisconnection, isPreviousSessionIdSet ? clientBeforeDisconnection : null);

            FILEID fileIdAfterDisconnection;

            ResponseChecker <CREATE_Response> createResponseChecker = null;
            if (isPreviousSessionIdSet)
            {
                if (testConfig.Platform == Platform.WindowsServer2012R2)
                {
                    // 6   Appendix A: Product Behavior
                    // <265> Section 3.3.5.9.7: If the Session was established by specifying PreviousSessionId in the SMB2 SESSION_SETUP request,
                    // therefore invalidating the previous session, Windows 8.1 and Windows Server 2012 R2 close the durable opens established on the previous session.
                    createResponseChecker = (header, response) =>
                    {
                        BaseTestSite.Assert.AreNotEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "{0} should not be successful if Server is Windows Server 2012R2 and the Session was established by specifying PreviousSessionId in the SMB2 SESSION_SETUP request. " +
                            "Actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));

                        BaseTestSite.CaptureRequirementIfAreEqual(
                            Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND,
                            header.Status,
                            RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id,
                            RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description);
                    };
                }
                else
                {
                    createResponseChecker = (header, response) =>
                    {
                        BaseTestSite.Assert.AreEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                    };
                }
            }
            else
            {
                createResponseChecker = (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should not be successful if Open.Session is not NULL, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));

                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND,
                        header.Status,
                        RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id,
                        RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description);
                };
            }

            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: createResponseChecker);
            #endregion

            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);

            clientAfterDisconnection.LogOff();

            clientAfterDisconnection.Disconnect();
        }
Example #23
0
        private void CreateFile(string uncShare, string fileName, int lengthInByte)
        {
            Site.Log.Add(
                LogEntryKind.Debug,
                "Create file {0} in share {1}", fileName, uncShare);

            Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);

            client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);

            client.CreditGoal = 32;

            client.Negotiate(
                new DialectRevision[] { ModelUtility.GetDialectRevision(config.MaxSmbVersionSupported) },
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_LARGE_MTU);

            client.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            uint tId;

            client.TreeConnect(
                uncShare,
                out tId);

            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fId;

            client.Create(
                tId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fId,
                out serverCreateContexts);

            string content;

            if (isMultiCreditSupportedOnConnection)
            {
                content = Smb2Utility.CreateRandomStringInByte(lengthInByte);
                client.Write(tId, fId, content);
            }
            else
            {
                // Write several times if server does not support multi credit
                int   writeTimes = lengthInByte / (64 * 1024);
                int   rest       = lengthInByte % (64 * 1024);
                ulong offset     = 0;

                for (int time = 0; time < writeTimes; time++)
                {
                    content = Smb2Utility.CreateRandomString(64);
                    client.Write(tId, fId, content, offset);
                    offset += 64 * 1024;
                }

                if (rest != 0)
                {
                    content = Smb2Utility.CreateRandomStringInByte(rest);
                    client.Write(tId, fId, content, offset);
                }
            }

            client.Close(tId, fId);

            client.TreeDisconnect(tId);

            client.LogOff();

            client.Disconnect();

            Site.Log.Add(
                LogEntryKind.Debug,
                "Create file {0} in share {1}", fileName, uncShare);
        }
        public void BVT_DurableHandleV1_Reconnect_WithBatchOplock()
        {
            /// 1. Client requests a durable handle with BatchOplock
            /// 2. Client sends Disconnect to lose connection
            /// 3. Client reconnects the durable handle with BatchOplock, and expects success.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb2002);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            fileName = "BVT_DurableHandleV1_Reconnect_WithBatchOplock" + Guid.NewGuid() + ".txt";
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);

            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends CREATE request, with OPLOCK_LEVEL_BATCH and SMB2_CREATE_DURABLE_HANDLE_REQUEST.", clientGuid);
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequest
                {
                    DurableRequest = Guid.Empty,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleResponseChecker(BaseTestSite));
            });

            clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "The client with clientGuid {0} connects to server and opens file with a durable handle.", clientGuid.ToString());
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The client with clientGuid {0} sends DISCONECT request.", clientGuid.ToString());
            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "The client with clientGuid {0} opens the same file and reconnects the durable handle.", clientGuid);

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb21, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends CREATE request, with OPLOCK_LEVEL_BATCH and SMB2_CREATE_DURABLE_HANDLE_RECONNECT.", clientGuid);
            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE);

            string readContent;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends READ request.", clientGuid.ToString());
            clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent);

            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "The written content is expected to be equal to read content.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the durable handle");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client with clientGuid {0} by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF; DISCONNECT.", clientGuid.ToString());
            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
            #endregion
        }
Example #25
0
        /// <summary>
        /// Operations after Negotiate, from Session Setup to Log off.
        /// </summary>
        private void PostNegotiateOperations(EnableEncryptionType enableEncryptionType, bool connectEncryptedShare)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request and expects response.");
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            if (enableEncryptionType == EnableEncryptionType.EnableEncryptionPerSession)
            {
                // After calling this method, client will send encrypted message after session setup
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables global encryption.");
                client.EnableSessionSigningAndEncryption(enableSigning: false, enableEncryption: true);
            }

            string uncSharepath =
                Smb2Utility.GetUncPath(TestConfig.SutComputerName, connectEncryptedShare ? TestConfig.EncryptedFileShare : TestConfig.BasicFileShare);
            uint treeId;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT to share: {0}", uncSharepath);
            client.TreeConnect(
                uncSharepath,
                out treeId,
                (Packet_Header header, TREE_CONNECT_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "TreeConnect should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                if (connectEncryptedShare)
                {
                    BaseTestSite.Assert.AreEqual(
                        ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA,
                        ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags,
                        "Server should set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response");
                }
                else
                {
                    BaseTestSite.Assert.AreNotEqual(
                        ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA,
                        ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags,
                        "Server should not set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response");
                }
            });

            if (enableEncryptionType == EnableEncryptionType.EnableEncryptionPerShare)
            {
                // After calling this method, client will send encrypted message after tree connect.
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables per share encryption: TreeId=0x{0:x}", treeId);
                client.SetTreeEncryption(treeId, true);
            }

            FILEID fileId;

            Smb2CreateContextResponse[] serverCreateContexts;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted CREATE request and expects success.");
            client.Create(
                treeId,
                CurrentTestCaseName + "_" + Guid.NewGuid() + ".txt",
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                out fileId,
                out serverCreateContexts);
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrpyted WRITE request and expects success.");
            client.Write(treeId, fileId, content);

            string actualContent;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted READ request and expects success.");
            client.Read(treeId, fileId, 0, (uint)content.Length, out actualContent);

            BaseTestSite.Assert.IsTrue(
                content.Equals(actualContent),
                "File content read should be identical to that has been written.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client.Close(treeId, fileId);
            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        private void AppInstanceIdTest(bool sameAppInstanceId, bool containCreateDurableContext)
        {
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region Client 1 Connect to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            clientForInitialOpen = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientForInitialOpen.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress);
            clientForInitialOpen.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            clientForInitialOpen.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeIdForInitialOpen;
            clientForInitialOpen.TreeConnect(sharePath, out treeIdForInitialOpen);

            Guid   appInstanceId = Guid.NewGuid();
            FILEID fileIdForInitialOpen;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends CREATE request for exclusive open with SMB2_CREATE_APP_INSTANCE_ID create context.");
            Smb2CreateContextResponse[] serverCreateContexts;
            Smb2CreateContextRequest[]  createContextsRequestForInitialOpen = null;
            if (containCreateDurableContext)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is also included in the CREATE request.");
                createContextsRequestForInitialOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateDurableHandleRequestV2
                    {
                        CreateGuid = Guid.NewGuid()
                    },
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = appInstanceId
                    }
                };
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is not included in the CREATE request.");
                createContextsRequestForInitialOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = appInstanceId
                    }
                };
            }

            clientForInitialOpen.Create(
                treeIdForInitialOpen,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdForInitialOpen,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                createContextsRequestForInitialOpen,
                shareAccess: ShareAccess_Values.NONE);
            #endregion

            #region Client 2 Connect to Server

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the second client by sending the following requests: NEGOTIATE; SESSION-SETUP; TREE_CONNECT");
            clientForReOpen = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientForReOpen.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic2IPAddress);
            clientForReOpen.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            clientForReOpen.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeIdForReOpen;
            clientForReOpen.TreeConnect(sharePath, out treeIdForReOpen);

            FILEID fileIdForReOpen;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The second client sends CREATE request for exclusive open with the {0} SMB2_CREATE_APP_INSTANCE_ID of the first client.", sameAppInstanceId ? "same" : "different");
            Smb2CreateContextRequest[] createContextsRequestForReOpen = null;
            if (containCreateDurableContext)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is also included in the CREATE request.");
                createContextsRequestForReOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateDurableHandleRequestV2
                    {
                        CreateGuid = Guid.NewGuid()
                    },
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = sameAppInstanceId ? appInstanceId : Guid.NewGuid()
                    }
                };
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is not included in the CREATE request.");
                createContextsRequestForReOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = sameAppInstanceId ? appInstanceId : Guid.NewGuid()
                    }
                };
            }

            clientForReOpen.Create(
                treeIdForReOpen,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdForReOpen,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                createContextsRequestForReOpen,
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                if (sameAppInstanceId)
                {
                    BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "The second client should create the open successfully.");
                }
                else
                {
                    BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, header.Status, "The second client should not create the open successfully.");
                }
            });

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends another WRITE request.");

            if (sameAppInstanceId)
            {
                clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, content,
                                           checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "The initial open is closed. Write should not succeed. Actually server returns with {0}.", Smb2Status.GetStatusCode(header.Status));
                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_FILE_CLOSED,
                        header.Status,
                        RequirementCategory.STATUS_FILE_CLOSED.Id,
                        RequirementCategory.STATUS_FILE_CLOSED.Description);
                });

                // The first open is closed, no need to do clean up job.
                // Clean up the second client.
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen);
                clientForReOpen.TreeDisconnect(treeIdForReOpen);
                clientForReOpen.LogOff();
                clientForReOpen.Disconnect();
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The initial open is not closed. Write should succeed.");
                clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, content);

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the first client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
                clientForInitialOpen.Close(treeIdForInitialOpen, fileIdForInitialOpen);
                clientForInitialOpen.TreeDisconnect(treeIdForInitialOpen);
                clientForInitialOpen.LogOff();

                // The second client doesn't create the open succesfully, so no need to close the open.
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                clientForReOpen.TreeDisconnect(treeIdForReOpen);
                clientForReOpen.LogOff();
                clientForReOpen.Disconnect();
            }

            #endregion
        }
        private void DurableHandleV2_Reconnect_WithLeaseV1(bool sameFileName, bool persistent = false)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(
                persistent ?
                NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES:
                NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE);
            #endregion

            string content    = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            Guid   clientGuid = Guid.NewGuid();
            durableHandleUncSharePath =
                persistent ? Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
            fileName = (persistent ? "PersistentHandle" : "DurableHandleV2") + "_Reconnect_WithLeaseV1" + Guid.NewGuid() + ".txt";

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a {0} handle", persistent ? "persistent" : "durable");

            uint treeIdBeforeDisconnection;
            Connect(
                DialectRevision.Smb30,
                clientBeforeDisconnection,
                clientGuid,
                testConfig.AccountCredential,
                persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert,
                out treeIdBeforeDisconnection,
                null);

            Guid                        createGuid = Guid.NewGuid();
            Guid                        leaseKey   = Guid.NewGuid();
            LeaseStateValues            leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
            FILEID                      fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            status = clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                    Flags      = persistent? CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0,
                },
                new Smb2CreateRequestLease
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(
                    serverCreateContexts,
                    new DefaultDurableHandleV2ResponseChecker(
                        BaseTestSite,
                        persistent ? CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0,
                        uint.MaxValue));
            });

            status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            #endregion

            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the {0} handle", persistent ? "durable" : "persistent");

            uint treeIdAfterDisconnection;
            Connect(
                DialectRevision.Smb30,
                clientAfterDisconnection,
                clientGuid,
                testConfig.AccountCredential,
                persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert,
                out treeIdAfterDisconnection,
                clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            status = clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                sameFileName ?
                fileName : (persistent ?
                            "PersistentHandle" : "DurableHandleV2" + "_Reconnect_WithLeaseV1_WithDifferentFileName" + Guid.NewGuid() + ".txt"),
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnectV2
                {
                    CreateGuid = createGuid,
                    Flags      = persistent ? CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0,
                    FileId     = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                },
                new Smb2CreateRequestLease
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) => { });

            if (sameFileName)
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect a durable handle should be successful");
                string readContent;
                status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent);

                BaseTestSite.Assert.IsTrue(
                    readContent.Equals(content),
                    "The written content should equal to read content.");
                clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            }
            else
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_INVALID_PARAMETER, status,
                    "If Open.Lease is not NULL and Open.FileName does not match the file name specified in the Buffer field of the SMB2 CREATE request, " +
                    "the server MUST fail the request with STATUS_INVALID_PARAMETER.");
            }

            #endregion

            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
        }
        /// <summary>
        /// Test CLIENT_MOVE_NOTIFICATION.
        /// </summary>
        /// <param name="expectedVersion">SwnVersion.SWN_VERSION_2 indicates that register with WitnessrRegisterEx, SwnVersion.SWN_VERSION_1 indicates that register with WitnessrRegister.</param>
        private void SWNAsyncNotification_ClientMove(SwnVersion expectedVersion)
        {
            int  ret    = 0;
            uint callId = 0;
            WITNESS_INTERFACE_INFO registerInterface;
            string server = TestConfig.ClusteredScaleOutFileServerName;

            #region Get the file server to access it through SMB2

            IPAddress currentAccessIp = SWNTestUtility.GetCurrentAccessIP(server);
            BaseTestSite.Assert.AreNotEqual(null, currentAccessIp, "IP address of the file server should NOT be empty");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Got the IP {0} to access the file server", currentAccessIp.ToString());

            #endregion

            #region Get register interface

            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIp,
                                                           TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                           TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, server), TestConfig.FailoverTimeout,
                           "Retry BindServer until succeed within timeout span");

            WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST();

            DoUntilSucceed(() =>
            {
                ret = swnClientForInterface.WitnessrGetInterfaceList(out interfaceList);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrGetInterfaceList returns with result code = 0x{0:x8}", ret);
                return(SWNTestUtility.VerifyInterfaceList(interfaceList, TestConfig.Platform));
            }, TestConfig.FailoverTimeout, "Retry to call WitnessrGetInterfaceList until succeed within timeout span");

            swnClientForInterface.SwnUnbind(TestConfig.Timeout);

            SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface);

            SWNTestUtility.CheckVersion(expectedVersion, (SwnVersion)registerInterface.Version);
            #endregion

            #region Register SWN witness

            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForWitness,
                                                           (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6),
                                                           TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                           TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, server), TestConfig.FailoverTimeout,
                           "Retry BindServer until succeed within timeout span");

            string clientName = Guid.NewGuid().ToString();
            string netName    = SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server);

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", netName);
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIp.ToString());
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName);

            if (SwnVersion.SWN_VERSION_2 == expectedVersion)
            {
                ret = swnClientForWitness.WitnessrRegisterEx(SwnVersion.SWN_VERSION_2,
                                                             netName,
                                                             null,
                                                             currentAccessIp.ToString(),
                                                             clientName,
                                                             WitnessrRegisterExFlagsValue.WITNESS_REGISTER_IP_NOTIFICATION,
                                                             120,
                                                             out pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegisterEx returns with result code = 0x{0:x8}", ret);
            }
            else
            {
                ret = swnClientForWitness.WitnessrRegister(SwnVersion.SWN_VERSION_1,
                                                           netName,
                                                           currentAccessIp.ToString(),
                                                           clientName,
                                                           out pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegister returns with result code = 0x{0:x8}", ret);
            }
            BaseTestSite.Assert.IsNotNull(pContext, "Expect pContext is not null.");

            callId = swnClientForWitness.WitnessrAsyncNotify(pContext);
            BaseTestSite.Assert.AreNotEqual <uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId);

            #endregion

            #region Create a file and write content

            string         uncSharePath  = Smb2Utility.GetUncPath(server, TestConfig.ClusteredFileShare);
            string         content       = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            string         testDirectory = CreateTestDirectory(uncSharePath);
            string         file          = Path.Combine(testDirectory, Guid.NewGuid().ToString());
            Guid           clientGuid    = Guid.NewGuid();
            Guid           createGuid    = Guid.NewGuid();
            FileServerType fsType        = FileServerType.ScaleOutFileServer;

            DoUntilSucceed(() => WriteContentBeforeFailover(fsType, server, currentAccessIp, uncSharePath, file, content, clientGuid, createGuid),
                           TestConfig.FailoverTimeout,
                           "Before failover, retry Write content until succeed within timeout span.");

            #endregion

            #region Move resource node

            // Move resource node to trigger CLIENT_MOVE_NOTIFICATION
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Move resource to interface {0} to trigger CLIENT_MOVE_NOTIFICATION", registerInterface.InterfaceGroupName);
            sutController.MoveSmbWitnessClient(clientName,
                                               SWNTestUtility.GetPrincipleName(TestConfig.DomainName, registerInterface.InterfaceGroupName));

            #endregion

            #region Wait CLIENT_MOVE_NOTIFICATION

            RESP_ASYNC_NOTIFY respNotify;
            // Wait the CLIENT_MOVE_NOTIFICATION
            ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
            BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrAsyncNotify returns with result code = 0x{0:x8}", ret);
            SWNTestUtility.PrintNotification(respNotify);

            // Verify RESP_ASYNC_NOTIFY
            SWNTestUtility.VerifyClientMoveShareMoveAndIpChange(respNotify, SwnMessageType.CLIENT_MOVE_NOTIFICATION, (uint)SwnIPAddrInfoFlags.IPADDR_V4, TestConfig.Platform);
            #endregion

            #region Get the new IpAddr
            IPADDR_INFO_LIST ipAddrInfoList;
            SwnUtility.ParseIPAddrInfoList(respNotify, out ipAddrInfoList);
            currentAccessIp = (ipAddrInfoList.IPAddrList[0].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(ipAddrInfoList.IPAddrList[0].IPV4) : SWNTestUtility.ConvertIPV6(ipAddrInfoList.IPAddrList[0].IPV6);
            #endregion

            #region Unregister SWN Witness

            ret = swnClientForWitness.WitnessrUnRegister(pContext);
            BaseTestSite.Assert.AreEqual <SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
            pContext = IntPtr.Zero;
            swnClientForWitness.SwnUnbind(TestConfig.Timeout);

            #endregion

            #region Make sure Cluster Share is available
            DoUntilSucceed(() => sutProtocolController.CheckIfShareIsAvailable(uncSharePath),
                           testConfig.Timeout,
                           "Make sure cluster share is available.");
            #endregion

            #region Read content and close the file
            DoUntilSucceed(() => ReadContentAfterFailover(server, currentAccessIp, uncSharePath, file, content, clientGuid, createGuid),
                           TestConfig.FailoverTimeout,
                           "Retry Read content until succeed within timeout span.");
            #endregion
        }
Example #29
0
        private void FileServerFailoverTest(string server, FileServerType fsType, bool reconnectWithoutFailover = false)
        {
            int       ret    = 0;
            uint      callId = 0;
            IPAddress currentAccessIpAddr            = null;
            WITNESS_INTERFACE_INFO registerInterface = new WITNESS_INTERFACE_INFO();
            WITNESS_INTERFACE_LIST interfaceList     = new WITNESS_INTERFACE_LIST();

            currentAccessIpAddr = SWNTestUtility.GetCurrentAccessIP(server);
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Get current file server IP: {0}.", currentAccessIpAddr);

            #region Register SWN witness
            if (witnessType == WitnessType.SwnWitness)
            {
                if (TestConfig.IsWindowsPlatform && fsType == FileServerType.ScaleOutFileServer)
                {
                    // Windows Server: when stopping a non-owner node of ScaleOutFS, no notication will be sent by SMB witness.
                    // So get one IP of the owner node of ScaleOutFS to access.
                    string      resourceOwnerNode = sutController.GetClusterResourceOwner(server);
                    IPAddress[] ownerIpList       = Dns.GetHostEntry(resourceOwnerNode).AddressList;
                    foreach (var ip in ownerIpList)
                    {
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Owner IP: {0}", ip);
                    }
                    if (!ownerIpList.Contains(currentAccessIpAddr))
                    {
                        currentAccessIpAddr = null;
                        IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList;
                        foreach (var ip in accessIpList)
                        {
                            if (ownerIpList.Contains(ip))
                            {
                                currentAccessIpAddr = ip;
                                break;
                            }
                        }
                        BaseTestSite.Assert.IsNotNull(currentAccessIpAddr, "IP should not be null.");
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Get the owner IP {0} as file server IP.", currentAccessIpAddr);
                    }

                    DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIpAddr,
                                                                   TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                                   TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, resourceOwnerNode), TestConfig.FailoverTimeout,
                                   "Retry BindServer until succeed within timeout span");
                }
                else
                {
                    DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIpAddr,
                                                                   TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                                   TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, server), TestConfig.FailoverTimeout,
                                   "Retry BindServer until succeed within timeout span");
                }

                DoUntilSucceed(() =>
                {
                    ret = swnClientForInterface.WitnessrGetInterfaceList(out interfaceList);
                    BaseTestSite.Assert.AreEqual <SwnErrorCode>(
                        SwnErrorCode.ERROR_SUCCESS,
                        (SwnErrorCode)ret,
                        "WitnessrGetInterfaceList returns with result code = 0x{0:x8}", ret);
                    return(SWNTestUtility.VerifyInterfaceList(interfaceList, TestConfig.Platform));
                }, TestConfig.FailoverTimeout, "Retry to call WitnessrGetInterfaceList until succeed within timeout span.");

                SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface);

                DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForWitness,
                                                               (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6),
                                                               TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                                                               TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, registerInterface.InterfaceGroupName), TestConfig.FailoverTimeout,
                               "Retry BindServer until succeed within timeout span");

                string clientName = Guid.NewGuid().ToString();

                BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:");
                BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server));
                BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIpAddr.ToString());
                BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName);

                ret = swnClientForWitness.WitnessrRegister(SwnVersion.SWN_VERSION_1, SWNTestUtility.GetPrincipleName(TestConfig.DomainName, server),
                                                           currentAccessIpAddr.ToString(), clientName, out pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(
                    SwnErrorCode.ERROR_SUCCESS,
                    (SwnErrorCode)ret,
                    "WitnessrRegister returns with result code = 0x{0:x8}", ret);
                BaseTestSite.Assert.IsNotNull(
                    pContext,
                    "Expect pContext is not null.");

                callId = swnClientForWitness.WitnessrAsyncNotify(pContext);
                BaseTestSite.Assert.AreNotEqual <uint>(
                    0,
                    callId,
                    "WitnessrAsyncNotify returns callId = {0}", callId);
            }
            #endregion

            #region Create a file and write content
            string uncSharePath  = Smb2Utility.GetUncPath(server, TestConfig.ClusteredFileShare);
            string content       = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            string testDirectory = CreateTestDirectory(uncSharePath);
            string file          = Path.Combine(testDirectory, Guid.NewGuid().ToString());
            Guid   clientGuid    = Guid.NewGuid();
            Guid   createGuid    = Guid.NewGuid();

            DoUntilSucceed(() => WriteContentBeforeFailover(fsType, server, currentAccessIpAddr, uncSharePath, file, content, clientGuid, createGuid),
                           TestConfig.FailoverTimeout,
                           "Before failover, retry Write content until succeed within timeout span.");
            #endregion

            #region Disable accessed node

            if (TestConfig.IsWindowsPlatform)
            {
                AssignCurrentAccessNode(server, fsType, currentAccessIpAddr);
            }


            if (!reconnectWithoutFailover)
            {
                BaseTestSite.Log.Add(
                    LogEntryKind.TestStep,
                    "Disable owner node for general file server or the node currently provides the access for scale-out file server.");
                FailoverServer(currentAccessIpAddr, server, fsType);
            }

            #endregion

            #region Wait for available server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Wait for available server.");
            if (witnessType == WitnessType.None)
            {
                if (fsType == FileServerType.GeneralFileServer)
                {
                    currentAccessIpAddr = null;
                    IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList;
                    DoUntilSucceed(() =>
                    {
                        foreach (IPAddress ipAddress in accessIpList)
                        {
                            Smb2FunctionalClient pingClient = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);

                            try
                            {
                                pingClient.ConnectToServerOverTCP(ipAddress);
                                pingClient.Disconnect();
                                pingClient = null;

                                currentAccessIpAddr = ipAddress;
                                return(true);
                            }
                            catch
                            {
                            }
                        }
                        return(false);
                    }, TestConfig.FailoverTimeout, "Retry to ping to server until succeed within timeout span");
                }
                else
                {
                    currentAccessIpAddr = null;

                    IPAddress[] accessIpList = Dns.GetHostEntry(server).AddressList;
                    foreach (IPAddress ipAddress in accessIpList)
                    {
                        if (TestConfig.IsWindowsPlatform)
                        {
                            // When setting failover mode to StopNodeService for Windows, SMB2 servers on two nodes can still be accessed by the client.
                            // So the client needs to get the new node to access it after failover by comparing host name.
                            if (string.Compare(currentAccessNode, Dns.GetHostEntry(ipAddress).HostName, true) == 0)
                            {
                                continue;
                            }
                        }
                        Smb2FunctionalClient pingClient = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);

                        try
                        {
                            pingClient.ConnectToServerOverTCP(ipAddress);
                            pingClient.Disconnect();
                            pingClient = null;

                            currentAccessIpAddr = ipAddress;
                            break;
                        }
                        catch
                        {
                        }
                    }
                }
            }
            else if (witnessType == WitnessType.SwnWitness)
            {
                // Verifying for notification
                RESP_ASYNC_NOTIFY respNotify;
                do
                {
                    // Wait the notification
                    ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
                    BaseTestSite.Assert.AreEqual <SwnErrorCode>(
                        SwnErrorCode.ERROR_SUCCESS,
                        (SwnErrorCode)ret,
                        "ExpectWitnessrAsyncNotify returns with result code = 0x{0:x8}", ret);
                    SWNTestUtility.PrintNotification(respNotify);

                    RESOURCE_CHANGE[] resourceChangeList;
                    SwnUtility.ParseResourceChange(respNotify, out resourceChangeList);
                    BaseTestSite.Assert.AreEqual <uint>(0x00000001, respNotify.NumberOfMessages, "Expect NumberOfMessages is set to 1.");

                    if (resourceChangeList[0].ChangeType == (uint)SwnResourceChangeType.RESOURCE_STATE_AVAILABLE)
                    {
                        // Verify RESP_ASYNC_NOTIFY, the resource is available
                        SWNTestUtility.VerifyResourceChange(respNotify, SwnResourceChangeType.RESOURCE_STATE_AVAILABLE);
                        break;
                    }

                    // Verify RESP_ASYNC_NOTIFY, the resource is unavailable
                    SWNTestUtility.VerifyResourceChange(respNotify, SwnResourceChangeType.RESOURCE_STATE_UNAVAILABLE);

                    callId = swnClientForWitness.WitnessrAsyncNotify(pContext);
                    BaseTestSite.Assert.AreNotEqual <uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId);
                } while (true);

                ret = swnClientForWitness.WitnessrUnRegister(pContext);
                BaseTestSite.Assert.AreEqual <SwnErrorCode>(
                    SwnErrorCode.ERROR_SUCCESS,
                    (SwnErrorCode)ret,
                    "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
                pContext = IntPtr.Zero;
                swnClientForWitness.SwnUnbind(TestConfig.Timeout);

                if (fsType == FileServerType.ScaleOutFileServer)
                {
                    // For scale-out file server case, retrieve and use another access IP for connection
                    currentAccessIpAddr =
                        (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6);
                }
            }
            #endregion

            #region Read content and close the file
            DoUntilSucceed(() => ReadContentAfterFailover(server, currentAccessIpAddr, uncSharePath, file, content, clientGuid, createGuid),
                           TestConfig.FailoverTimeout,
                           "After failover, retry Read content until succeed within timeout span.");
            #endregion
        }
        public void BVT_SMB2Basic_LockAndUnLock()
        {
            uint   status;
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region From client1 lock a byte range and try to write content to the file within the range
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client1 locks a byte range and try to write content to the file within the range.");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client1 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            status = client1.TreeConnect(uncSharePath, out treeId1);
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId1;
            string fileName = Guid.NewGuid().ToString() + ".txt";
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 writes content to the file created.");
            status = client1.Write(treeId1, fileId1, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending CLOSE request.");
            client1.Close(treeId1, fileId1);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 sends CREATE request.");
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locks        = new LOCK_ELEMENT[1];
            uint           lockSequence = 0;
            locks[0].Offset = 0;
            locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024;
            locks[0].Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 starts to lock a byte range for file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locks[0].Offset, locks[0].Length, locks[0].Flags.ToString());
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 sends WRITE request to write content to the locking range");
            status = client1.Write(
                treeId1,
                fileId1,
                content,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    header.Status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            });
            #endregion

            #region From client2 to read and write the locking range of the same file after lock
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client2 to read and take shared lock on the locking range of the same file after lock");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client2 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client2.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client2.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId2;
            status = client2.TreeConnect(uncSharePath, out treeId2);
            FILEID fileId2;
            status = client2.Create(
                treeId2,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId2,
                out serverCreateContexts);

            string data;
            Random random = new Random();
            uint   offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1);
            uint   length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends READ request to read a random area in the locking range of file \"{0}\" with offset: {1}, length: {2}",
                fileName, offset, length);
            status = client2.Read(treeId2, fileId2, offset, length, out data);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locksFromOtherOpen = new LOCK_ELEMENT[1];
            locksFromOtherOpen[0].Offset = offset;
            locksFromOtherOpen[0].Length = (ulong)length;
            locksFromOtherOpen[0].Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to take a shared lock on random range of file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locksFromOtherOpen[0].Offset, locksFromOtherOpen[0].Length, locksFromOtherOpen[0].Flags.ToString());
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to unlock the range");
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write a random area in the locking range of file \"{0}\" after lock", fileName);
            status = client2.Write(
                treeId2,
                fileId2,
                content,
                offset,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    header.Status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            });
            #endregion

            #region From client1 unlock the range
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 unlocks the range");
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client1 attempts to unlock the range");
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
            #endregion

            #region From client2 write content to the previous locking range after unlock
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write content to the previous locking range after unlock");
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client2 attempts to write a random area in the locking range of file \"{0}\" after unlock", fileName);
            status = client2.Write(treeId2, fileId2, content, offset);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client2 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client2.Close(treeId2, fileId2);
            client2.TreeDisconnect(treeId2);
            client2.LogOff();
            #endregion
        }