Jelajahi Sumber

iSCSI Console v1.2.8

Tal Aloni 8 tahun lalu
induk
melakukan
8255f2eeca

+ 2 - 2
ISCSI/Properties/AssemblyInfo.cs

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
 //
 // You can specify all the values or you can default the Revision and Build Numbers 
 // by using the '*' as shown below:
-[assembly: AssemblyVersion("1.2.7.0")]
-[assembly: AssemblyFileVersion("1.2.7.0")]
+[assembly: AssemblyVersion("1.2.8.0")]
+[assembly: AssemblyFileVersion("1.2.8.0")]

+ 2 - 0
ISCSI/RevisionHistory.txt

@@ -58,3 +58,5 @@ Revision History:
 1.2.6 - Minor improvements.
 
 1.2.7 - The iSCSI Client did not report the correct disk capacity.
+
+1.2.8 - Reject improper commands during the login phase.

+ 67 - 59
ISCSI/Server/ISCSIServer.cs

@@ -325,22 +325,7 @@ namespace ISCSI.Server
                 }
             }
 
-            if (pdu is NOPOutPDU)
-            {
-                NOPOutPDU request = (NOPOutPDU)pdu;
-                if (request.InitiatorTaskTag != 0xFFFFFFFF)
-                {
-                    NOPInPDU response = ServerResponseHelper.GetNOPResponsePDU(request);
-                    TrySendPDU(state, response);
-                }
-            }
-            else if (pdu is TextRequestPDU)
-            {
-                TextRequestPDU request = (TextRequestPDU)pdu;
-                TextResponsePDU response = ServerResponseHelper.GetTextResponsePDU(request, m_targets);
-                TrySendPDU(state, response);
-            }
-            else if (pdu is LoginRequestPDU)
+            if (pdu is LoginRequestPDU)
             {
                 LoginRequestPDU request = (LoginRequestPDU)pdu;
                 Log("[{0}][ReceiveCallback] Login Request, current stage: {1}, next stage: {2}, parameters: {3}", state.ConnectionIdentifier, request.CurrentStage, request.NextStage, KeyValuePairUtils.ToString(request.LoginParameters));
@@ -368,12 +353,6 @@ namespace ISCSI.Server
                 LoginResponsePDU response = ServerResponseHelper.GetLoginResponsePDU(request, m_targets, state.SessionParameters, state.ConnectionParameters, ref state.Target, GetNextTSIH);
                 if (state.Target != null)
                 {
-                    if (request.LoginParameters.ContainsKey("TargetMaxRecvDataSegmentLength"))
-                    {
-                        state.ConnectionParameters.InitiatorMaxRecvDataSegmentLength = Convert.ToInt32(request.LoginParameters.ValueOf("TargetMaxRecvDataSegmentLength"));
-                        Log("[{0}][ProcessPDU] Initiator's TargetMaxRecvDataSegmentLength: {1}", state.ConnectionIdentifier, state.ConnectionParameters.InitiatorMaxRecvDataSegmentLength);
-                    }
-
                     state.SessionParameters.ISID = request.ISID;
                     state.ConnectionParameters.CID = request.CID;
 
@@ -385,60 +364,89 @@ namespace ISCSI.Server
                 Log("[{0}][ReceiveCallback] Login Response parameters: {1}", state.ConnectionIdentifier, KeyValuePairUtils.ToString(response.LoginParameters));
                 TrySendPDU(state, response);
             }
-            else if (pdu is LogoutRequestPDU)
+            else if (!state.SessionParameters.IsDiscovery && state.Target == null)
             {
-                lock (m_activeConnectionsLock)
+                // Before the Full Feature Phase is established, only Login Request and Login Response PDUs are allowed.
+                Log("[{0}][ProcessPDU] Improper command during login phase, OpCode: 0x{1}", state.ConnectionIdentifier, pdu.OpCode.ToString("x"));
+                // A target receiving any PDU except a Login request before the Login phase is started MUST
+                // immediately terminate the connection on which the PDU was received.
+                // Once the Login phase has started, if the target receives any PDU except a Login request,
+                // it MUST send a Login reject (with Status "invalid during login") and then disconnect.
+                clientSocket.Close();
+            }
+            else // Logged in
+            {
+                if (pdu is TextRequestPDU)
                 {
-                    int connectionIndex = GetStateObjectIndex(m_activeConnections, state.SessionParameters.ISID, state.SessionParameters.TSIH, state.ConnectionParameters.CID);
-                    if (connectionIndex >= 0)
+                    TextRequestPDU request = (TextRequestPDU)pdu;
+                    TextResponsePDU response = ServerResponseHelper.GetTextResponsePDU(request, m_targets);
+                    TrySendPDU(state, response);
+                }
+                else if (pdu is LogoutRequestPDU)
+                {
+                    lock (m_activeConnectionsLock)
                     {
-                        lock (m_activeConnections[connectionIndex].Target.IOLock)
+                        int connectionIndex = GetStateObjectIndex(m_activeConnections, state.SessionParameters.ISID, state.SessionParameters.TSIH, state.ConnectionParameters.CID);
+                        if (connectionIndex >= 0)
                         {
-                            // Wait for pending I/O to complete.
+                            lock (m_activeConnections[connectionIndex].Target.IOLock)
+                            {
+                                // Wait for pending I/O to complete.
+                            }
+                            m_activeConnections.RemoveAt(connectionIndex);
                         }
-                        m_activeConnections.RemoveAt(connectionIndex);
                     }
+                    LogoutRequestPDU request = (LogoutRequestPDU)pdu;
+                    LogoutResponsePDU response = ServerResponseHelper.GetLogoutResponsePDU(request);
+                    TrySendPDU(state, response);
+                    clientSocket.Close(); // We can close the connection now
                 }
-                LogoutRequestPDU request = (LogoutRequestPDU)pdu;
-                LogoutResponsePDU response = ServerResponseHelper.GetLogoutResponsePDU(request);
-                TrySendPDU(state, response);
-                clientSocket.Close(); // We can close the connection now
-            }
-            else // Target commands
-            {
-                if (state.SessionParameters.IsDiscovery || state.Target == null)
+                else if (state.SessionParameters.IsDiscovery)
                 {
-                    Log("[{0}][ProcessPDU] Unknown or improper command during discovery session, OpCode: 0x{1}", state.ConnectionIdentifier, pdu.OpCode.ToString("x"));
+                    // The target MUST ONLY accept text requests with the SendTargets key and a logout
+                    // request with the reason "close the session".  All other requests MUST be rejected.
+                    Log("[{0}][ProcessPDU] Improper command during discovery session, OpCode: 0x{1}", state.ConnectionIdentifier, pdu.OpCode.ToString("x"));
+                    RejectPDU reject = new RejectPDU();
+                    reject.Reason = RejectReason.ProtocolError;
+                    reject.Data = ByteReader.ReadBytes(pdu.GetBytes(), 0, 48);
+
+                    TrySendPDU(state, reject);
                 }
-                else // Logged in to target 
+                else if (pdu is NOPOutPDU)
                 {
-                    // FIXME: the iSCSI target layer MUST deliver the commands for execution (to the SCSI execution engin) in the order specified by CmdSN
-                    // e.g. read requests should not be executed while previous write request data is being received (via R2T)
-                    if (pdu is SCSIDataOutPDU)
+                    NOPOutPDU request = (NOPOutPDU)pdu;
+                    if (request.InitiatorTaskTag != 0xFFFFFFFF)
                     {
-                        SCSIDataOutPDU request = (SCSIDataOutPDU)pdu;
-                        ISCSIServer.Log("[{0}][ProcessPDU] SCSIDataOutPDU: Target transfer tag: {1}, LUN: {2}, Buffer offset: {3}, Data segment length: {4}, DataSN: {5}, Final: {6}", state.ConnectionIdentifier, request.TargetTransferTag, (ushort)request.LUN, request.BufferOffset, request.DataSegmentLength, request.DataSN, request.Final);
-                        ISCSIPDU response = TargetResponseHelper.GetSCSIDataOutResponsePDU(request, state.Target, state.SessionParameters, state.ConnectionParameters);
+                        NOPInPDU response = ServerResponseHelper.GetNOPResponsePDU(request);
                         TrySendPDU(state, response);
                     }
-                    else if (pdu is SCSICommandPDU)
+                }
+                else if (pdu is SCSIDataOutPDU)
+                {
+                    // FIXME: the iSCSI target layer MUST deliver the commands for execution (to the SCSI execution engin) in the order specified by CmdSN
+                    // e.g. read requests should not be executed while previous write request data is being received (via R2T)
+                    SCSIDataOutPDU request = (SCSIDataOutPDU)pdu;
+                    ISCSIServer.Log("[{0}][ProcessPDU] SCSIDataOutPDU: Target transfer tag: {1}, LUN: {2}, Buffer offset: {3}, Data segment length: {4}, DataSN: {5}, Final: {6}", state.ConnectionIdentifier, request.TargetTransferTag, (ushort)request.LUN, request.BufferOffset, request.DataSegmentLength, request.DataSN, request.Final);
+                    ISCSIPDU response = TargetResponseHelper.GetSCSIDataOutResponsePDU(request, state.Target, state.SessionParameters, state.ConnectionParameters);
+                    TrySendPDU(state, response);
+                }
+                else if (pdu is SCSICommandPDU)
+                {
+                    SCSICommandPDU command = (SCSICommandPDU)pdu;
+                    ISCSIServer.Log("[{0}][ProcessPDU] SCSICommandPDU: CmdSN: {1}, LUN: {2}, Data segment length: {3}, Expected Data Transfer Length: {4}, Final: {5}", state.ConnectionIdentifier, command.CmdSN, (ushort)command.LUN, command.DataSegmentLength, command.ExpectedDataTransferLength, command.Final);
+                    List<ISCSIPDU> scsiResponseList = TargetResponseHelper.GetSCSIResponsePDU(command, state.Target, state.SessionParameters, state.ConnectionParameters);
+                    foreach (ISCSIPDU response in scsiResponseList)
                     {
-                        SCSICommandPDU command = (SCSICommandPDU)pdu;
-                        ISCSIServer.Log("[{0}][ProcessPDU] SCSICommandPDU: CmdSN: {1}, LUN: {2}, Data segment length: {3}, Expected Data Transfer Length: {4}, Final: {5}", state.ConnectionIdentifier, command.CmdSN, (ushort)command.LUN, command.DataSegmentLength, command.ExpectedDataTransferLength, command.Final);
-                        List<ISCSIPDU> scsiResponseList = TargetResponseHelper.GetSCSIResponsePDU(command, state.Target, state.SessionParameters, state.ConnectionParameters);
-                        foreach (ISCSIPDU response in scsiResponseList)
+                        TrySendPDU(state, response);
+                        if (!clientSocket.Connected)
                         {
-                            TrySendPDU(state, response);
-                            if (!clientSocket.Connected)
-                            {
-                                return;
-                            }
+                            return;
                         }
                     }
-                    else
-                    {
-                        Log("[{0}][ProcessPDU] Unknown or improper command, OpCode: 0x{1}", state.ConnectionIdentifier, pdu.OpCode.ToString("x"));
-                    }
+                }
+                else
+                {
+                    Log("[{0}][ProcessPDU] Unsupported command, OpCode: 0x{1}", state.ConnectionIdentifier, pdu.OpCode.ToString("x"));
                 }
             }
         }

+ 2 - 2
ISCSIConsole/Properties/AssemblyInfo.cs

@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
 //      Build Number
 //      Revision
 //
-[assembly: AssemblyVersion("1.2.7.0")]
-[assembly: AssemblyFileVersion("1.2.7.0")]
+[assembly: AssemblyVersion("1.2.8.0")]
+[assembly: AssemblyFileVersion("1.2.8.0")]

+ 2 - 0
ISCSIConsole/RevisionHistory.txt

@@ -57,3 +57,5 @@ Revision History:
 1.2.6 - Updates to the ISCSI library.
 
 1.2.7 - Updates to the ISCSI library.
+
+1.2.8 - Updates to the ISCSI library.