Client: Enabled SMB 2.1 Large MTU support

This commit is contained in:
Tal Aloni 2020-01-31 16:24:29 +02:00
parent 2ee081ab51
commit b4652935c6
2 changed files with 48 additions and 6 deletions

View file

@ -24,9 +24,10 @@ namespace SMBLibrary.Client
public const int NetBiosOverTCPPort = 139;
public const int DirectTCPPort = 445;
public const uint ClientMaxTransactSize = 65536;
public const uint ClientMaxReadSize = 65536;
public const uint ClientMaxWriteSize = 65536;
public static readonly uint ClientMaxTransactSize = 8388608;
public static readonly uint ClientMaxReadSize = 8388608;
public static readonly uint ClientMaxWriteSize = 8388608;
private static readonly ushort DesiredCredits = 128;
private SMBTransportType m_transport;
private bool m_isConnected;
@ -49,6 +50,7 @@ namespace SMBLibrary.Client
private ulong m_sessionID;
private byte[] m_securityBlob;
private byte[] m_sessionKey;
private ushort m_availableCredits = 1;
public SMB2Client()
{
@ -388,6 +390,8 @@ namespace SMBLibrary.Client
return;
}
m_availableCredits += command.Header.Credits;
// [MS-SMB2] 3.2.5.1.2 - If the MessageId is 0xFFFFFFFFFFFFFFFF, this is not a reply to a previous request,
// and the client MUST NOT attempt to locate the request, but instead process it as follows:
// If the command field in the SMB2 header is SMB2 OPLOCK_BREAK, it MUST be processed as specified in 3.2.5.19.
@ -469,7 +473,32 @@ namespace SMBLibrary.Client
internal void TrySendCommand(SMB2Command request)
{
request.Header.Credits = 1;
if (m_dialect == SMB2Dialect.SMB202 || m_transport == SMBTransportType.NetBiosOverTCP)
{
request.Header.CreditCharge = 0;
request.Header.Credits = 1;
m_availableCredits -= 1;
}
else
{
if (request.Header.CreditCharge == 0)
{
request.Header.CreditCharge = 1;
}
if (m_availableCredits < request.Header.CreditCharge)
{
throw new Exception("Not enough credits");
}
m_availableCredits -= request.Header.CreditCharge;
if (m_availableCredits < DesiredCredits)
{
request.Header.Credits += (ushort)(DesiredCredits - m_availableCredits);
}
}
request.Header.MessageID = m_messageID;
request.Header.SessionID = m_sessionID;
if (m_signingRequired)
@ -485,7 +514,14 @@ namespace SMBLibrary.Client
}
}
TrySendCommand(m_clientSocket, request);
m_messageID++;
if (m_dialect == SMB2Dialect.SMB202 || m_transport == SMBTransportType.NetBiosOverTCP)
{
m_messageID++;
}
else
{
m_messageID += request.Header.CreditCharge;
}
}
public uint MaxTransactSize

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017-2019 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2017-2020 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -13,6 +13,8 @@ namespace SMBLibrary.Client
{
public class SMB2FileStore : ISMBFileStore
{
private const int BytesPerCredit = 65536;
private SMB2Client m_client;
private uint m_treeID;
@ -69,6 +71,7 @@ namespace SMBLibrary.Client
{
data = null;
ReadRequest request = new ReadRequest();
request.Header.CreditCharge = (ushort)Math.Ceiling((double)maxCount / BytesPerCredit);
request.FileId = (FileID)handle;
request.Offset = (ulong)offset;
request.ReadLength = (uint)maxCount;
@ -91,6 +94,7 @@ namespace SMBLibrary.Client
{
numberOfBytesWritten = 0;
WriteRequest request = new WriteRequest();
request.Header.CreditCharge = (ushort)Math.Ceiling((double)data.Length / BytesPerCredit);
request.FileId = (FileID)handle;
request.Offset = (ulong)offset;
request.Data = data;
@ -128,6 +132,7 @@ namespace SMBLibrary.Client
{
result = new List<QueryDirectoryFileInformation>();
QueryDirectoryRequest request = new QueryDirectoryRequest();
request.Header.CreditCharge = (ushort)Math.Ceiling((double)m_client.MaxTransactSize / BytesPerCredit);
request.FileInformationClass = informationClass;
request.Reopen = true;
request.FileId = (FileID)handle;
@ -279,6 +284,7 @@ namespace SMBLibrary.Client
{
output = null;
IOCtlRequest request = new IOCtlRequest();
request.Header.CreditCharge = (ushort)Math.Ceiling((double)maxOutputLength / BytesPerCredit);
request.CtlCode = ctlCode;
request.IsFSCtl = true;
request.FileId = (FileID)handle;