Exemple #1
0
        internal static SCSICommandPDU GetReportLUNsCommand(SessionParameters session, ConnectionParameters connection, uint allocationLength)
        {
            SCSICommandDescriptorBlock reportLUNs = SCSICommandDescriptorBlock.Create(SCSIOpCodeName.ReportLUNs);

            reportLUNs.TransferLength = allocationLength;

            SCSICommandPDU scsiCommand = new SCSICommandPDU();

            scsiCommand.CommandDescriptorBlock = reportLUNs.GetBytes();
            scsiCommand.InitiatorTaskTag       = session.GetNextTaskTag();
            scsiCommand.Final = true;
            scsiCommand.Read  = true;
            scsiCommand.CmdSN = session.GetNextCmdSN(true);
            scsiCommand.ExpectedDataTransferLength = allocationLength;
            return(scsiCommand);
        }
Exemple #2
0
        internal static SCSICommandPDU GetReadCapacity10Command(SessionParameters session, ConnectionParameters connection, ushort LUN)
        {
            SCSICommandDescriptorBlock readCapacity10 = SCSICommandDescriptorBlock.Create(SCSIOpCodeName.ReadCapacity10);

            readCapacity10.TransferLength = ReadCapacity10Parameter.Length;

            SCSICommandPDU scsiCommand = new SCSICommandPDU();

            scsiCommand.CommandDescriptorBlock = readCapacity10.GetBytes();
            scsiCommand.InitiatorTaskTag       = session.GetNextTaskTag();
            scsiCommand.Final = true;
            scsiCommand.Read  = true;
            scsiCommand.LUN   = LUN;
            scsiCommand.CmdSN = session.GetNextCmdSN(true);
            scsiCommand.ExpectedDataTransferLength = ReadCapacity10Parameter.Length;
            return(scsiCommand);
        }
Exemple #3
0
        public SCSIStatusCodeName ExecuteCommand(byte[] commandBytes, LUNStructure lun, byte[] data, out byte[] response)
        {
            SCSICommandDescriptorBlock command;

            try
            {
                command = SCSICommandDescriptorBlock.FromBytes(commandBytes, 0);
            }
            catch (UnsupportedSCSICommandException)
            {
                ISCSIServer.Log("[ExecuteCommand] Unsupported SCSI Command (0x{0})", commandBytes[0].ToString("X"));
                response = SCSITarget.FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }

            return(ExecuteCommand(command, lun, data, out response));
        }
Exemple #4
0
        internal static SCSICommandPDU GetRead16Command(SessionParameters session, ConnectionParameters connection, ushort LUN, ulong sectorIndex, uint sectorCount, int bytesPerSector)
        {
            SCSICommandDescriptorBlock read16 = SCSICommandDescriptorBlock.Create(SCSIOpCodeName.Read16);

            read16.LogicalBlockAddress64 = sectorIndex;
            read16.TransferLength        = sectorCount;

            SCSICommandPDU scsiCommand = new SCSICommandPDU();

            scsiCommand.CommandDescriptorBlock = read16.GetBytes();
            scsiCommand.LUN = LUN;
            scsiCommand.InitiatorTaskTag           = session.GetNextTaskTag();
            scsiCommand.Final                      = true;
            scsiCommand.Read                       = true;
            scsiCommand.CmdSN                      = session.GetNextCmdSN(true);
            scsiCommand.ExpectedDataTransferLength = (uint)(sectorCount * bytesPerSector);
            return(scsiCommand);
        }
Exemple #5
0
        internal static SCSICommandPDU GetReadCapacity16Command(ConnectionParameters connection, ushort LUN)
        {
            ISCSISession session = connection.Session;
            SCSICommandDescriptorBlock serviceActionIn = SCSICommandDescriptorBlock.Create(SCSIOpCodeName.ServiceActionIn16);

            serviceActionIn.ServiceAction  = ServiceAction.ReadCapacity16;
            serviceActionIn.TransferLength = ReadCapacity16Parameter.Length;

            SCSICommandPDU scsiCommand = new SCSICommandPDU();

            scsiCommand.CommandDescriptorBlock = serviceActionIn.GetBytes();
            scsiCommand.InitiatorTaskTag       = session.GetNextTaskTag();
            scsiCommand.Final = true;
            scsiCommand.Read  = true;
            scsiCommand.LUN   = LUN;
            scsiCommand.CmdSN = session.GetNextCmdSN(true);
            scsiCommand.ExpectedDataTransferLength = ReadCapacity16Parameter.Length;
            return(scsiCommand);
        }
Exemple #6
0
        public SCSIStatusCodeName Read(SCSICommandDescriptorBlock command, LUNStructure lun, out byte[] response)
        {
            if (lun >= m_disks.Count)
            {
                response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidLUNSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }

            Disk disk        = m_disks[lun];
            int  sectorCount = (int)command.TransferLength;

            try
            {
                lock (IOLock)
                {
                    response = disk.ReadSectors((long)command.LogicalBlockAddress64, sectorCount);
                }
                return(SCSIStatusCodeName.Good);
            }
            catch (ArgumentOutOfRangeException)
            {
                ISCSIServer.Log("[Read] Read error: LBA out of range");
                response = FormatSenseData(SenseDataParameter.GetIllegalRequestLBAOutOfRangeSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }
            catch (IOException ex)
            {
                int error = Marshal.GetHRForException(ex);
                if (error == (int)Win32Error.ERROR_CRC)
                {
                    ISCSIServer.Log("[Read] Read error: CRC error");
                    response = FormatSenseData(SenseDataParameter.GetWriteFaultSenseData());
                    return(SCSIStatusCodeName.CheckCondition);
                }
                else
                {
                    ISCSIServer.Log("[Read] Read error: {0}", ex.ToString());
                    response = FormatSenseData(SenseDataParameter.GetMediumErrorUnrecoverableReadErrorSenseData());
                    return(SCSIStatusCodeName.CheckCondition);
                }
            }
        }
        public void HandleCommand(byte[] packet)
        {
            var command = SCSICommandDescriptorBlock.DecodeCommand(packet, 0);

            this.Log(LogLevel.Debug, "Decoded command: {0}", command);
            switch (command)
            {
            case SCSICommand.TestUnitReady:
                break;

            case SCSICommand.Inquiry:
                // this is just an empty stub
                QueueData(new byte[36]);
                break;

            case SCSICommand.Read10:
                var cmd = Packet.DecodeDynamic <IReadWrite10Command>(packet, 0);
                this.Log(LogLevel.Debug, "Command args: LogicalBlockAddress: 0x{0:x}, TransferLength: {1}", (uint)cmd.LogicalBlockAddress, (ushort)cmd.TransferLength);
                var bytesCount   = (int)(cmd.TransferLength * BlockSize);
                var readPosition = (long)cmd.LogicalBlockAddress * BlockSize;
                dataBackend.Position = readPosition;
                var data = dataBackend.ReadBytes(bytesCount);
                this.Log(LogLevel.Debug, "Reading {0} bytes from address 0x{1:x}", bytesCount, readPosition);
                QueueData(data);
                break;

            case SCSICommand.ModeSense6:
                // this is just an empty stub
                QueueData(new byte[192]);
                break;

            case SCSICommand.RequestSense:
                // this is just an empty stub
                QueueData(new byte[512]);
                break;

            default:
                this.Log(LogLevel.Error, "Unsupported SCSI command: {0}", command);
                break;
            }
        }
Exemple #8
0
        public SCSIStatusCodeName Write(SCSICommandDescriptorBlock command, LUNStructure lun, byte[] data, out byte[] response)
        {
            if (lun >= m_disks.Count)
            {
                response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidLUNSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }

            Disk disk = m_disks[lun];

            if (disk.IsReadOnly)
            {
                SenseDataParameter senseData = SenseDataParameter.GetDataProtectSenseData();
                response = senseData.GetBytes();
                return(SCSIStatusCodeName.CheckCondition);
            }

            try
            {
                lock (IOLock)
                {
                    disk.WriteSectors((long)command.LogicalBlockAddress64, data);
                }
                response = new byte[0];
                return(SCSIStatusCodeName.Good);
            }
            catch (ArgumentOutOfRangeException)
            {
                ISCSIServer.Log("[Write] Write error: LBA out of range");
                response = FormatSenseData(SenseDataParameter.GetIllegalRequestLBAOutOfRangeSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }
            catch (IOException ex)
            {
                ISCSIServer.Log("[Write] Write error: {0}", ex.ToString());
                response = FormatSenseData(SenseDataParameter.GetMediumErrorWriteFaultSenseData());
                return(SCSIStatusCodeName.CheckCondition);
            }
        }
Exemple #9
0
        internal static SCSICommandPDU GetWrite16Command(SessionParameters session, ConnectionParameters connection, ushort LUN, ulong sectorIndex, byte[] data, int bytesPerSector)
        {
            SCSICommandDescriptorBlock write16 = SCSICommandDescriptorBlock.Create(SCSIOpCodeName.Write16);

            write16.LogicalBlockAddress64 = sectorIndex;
            write16.TransferLength        = (uint)(data.Length / bytesPerSector);

            SCSICommandPDU scsiCommand = new SCSICommandPDU();

            scsiCommand.CommandDescriptorBlock = write16.GetBytes();
            if (session.ImmediateData)
            {
                int immediateDataLength = Math.Min(data.Length, session.FirstBurstLength);
                scsiCommand.Data = ByteReader.ReadBytes(data, 0, immediateDataLength);
            }
            scsiCommand.LUN = LUN;
            scsiCommand.InitiatorTaskTag           = session.GetNextTaskTag();
            scsiCommand.Final                      = true;
            scsiCommand.Write                      = true;
            scsiCommand.CmdSN                      = session.GetNextCmdSN(true);
            scsiCommand.ExpectedDataTransferLength = (uint)(data.Length);
            return(scsiCommand);
        }
        private void HandleCommand(byte[] packet)
        {
            if (!BulkOnlyTransportCommandBlockWrapper.TryParse(packet, out var commandBlockWrapper))
            {
                this.Log(LogLevel.Warning, "Broken SCSI command block wrapper detected. Ignoring it.");
                return;
            }

            this.Log(LogLevel.Noisy, "Parsed command block wrapper: {0}", commandBlockWrapper);
            var command = SCSICommandDescriptorBlock.DecodeCommand(packet, BulkOnlyTransportCommandBlockWrapper.CommandOffset);

            this.Log(LogLevel.Noisy, "Decoded command: {0}", command);
            switch (command)
            {
            case SCSICommand.TestUnitReady:
                SendResult(commandBlockWrapper);
                break;

            case SCSICommand.Inquiry:
                // this is just an empty stub
                SendData(new byte[36]);
                SendResult(commandBlockWrapper);
                break;

            case SCSICommand.ReadCapacity:
                var result = new ReadCapcity10Result
                {
                    BlockLengthInBytes          = BlockSize,
                    ReturnedLogicalBlockAddress = (uint)(dataBackend.Length / BlockSize - 1)
                };
                SendData(Packet.Encode(result));
                SendResult(commandBlockWrapper);
                break;

            case SCSICommand.Read10:
                var cmd = Packet.DecodeDynamic <IReadWrite10Command>(packet, BulkOnlyTransportCommandBlockWrapper.CommandOffset);
                this.Log(LogLevel.Noisy, "Command args: LogicalBlockAddress: 0x{0:x}, TransferLength: {1}", (uint)cmd.LogicalBlockAddress, (ushort)cmd.TransferLength);
                var bytesCount   = (int)(cmd.TransferLength * BlockSize);
                var readPosition = (long)cmd.LogicalBlockAddress * BlockSize;
                dataBackend.Position = readPosition;
                var data = dataBackend.ReadBytes(bytesCount);
                this.Log(LogLevel.Noisy, "Reading {0} bytes from address 0x{1:x}", bytesCount, readPosition);
                SendData(data);
                SendResult(commandBlockWrapper, CommandStatus.Success, (uint)(commandBlockWrapper.DataTransferLength - data.Length));
                break;

            case SCSICommand.Write10:
                // the actual write will be triggered after receiving the next packet with data
                // we should not send result now
                writeCommandWrapper    = commandBlockWrapper;
                writeCommandDescriptor = Packet.DecodeDynamic <IReadWrite10Command>(packet, BulkOnlyTransportCommandBlockWrapper.CommandOffset);
                var position = (long)((dynamic)writeCommandDescriptor).LogicalBlockAddress * BlockSize;
                dataBackend.Position = position;
                bytesToWrite         = (uint)((dynamic)writeCommandDescriptor).TransferLength * BlockSize;
                this.Log(LogLevel.Noisy, "Preparing to write {1} bytes of data at address: 0x{0:x}", dataBackend.Position, bytesToWrite);
                mode = Mode.Data;
                break;

            case SCSICommand.ModeSense6:
                // this is just an empty stub
                SendData(new byte[192]);
                SendResult(commandBlockWrapper);
                break;

            case SCSICommand.RequestSense:
                // this is just an empty stub
                SendData(new byte[commandBlockWrapper.DataTransferLength]);
                SendResult(commandBlockWrapper);
                break;

            default:
                this.Log(LogLevel.Warning, "Unsupported SCSI command: {0}", command);
                SendResult(commandBlockWrapper, CommandStatus.Failure, commandBlockWrapper.DataTransferLength);
                break;
            }
        }
Exemple #11
0
 public SCSIStatusCodeName ExecuteCommand(SCSICommandDescriptorBlock command, LUNStructure lun, byte[] data, out byte[] response)
 {
     ISCSIServer.Log("[ExecuteCommand] {0}", command.OpCode);
     if (command.OpCode == SCSIOpCodeName.TestUnitReady)
     {
         return(TestUnitReady(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.RequestSense)
     {
         return(RequestSense(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Inquiry)
     {
         return(Inquiry((InquiryCommand)command, lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Reserve6)
     {
         return(Reserve6(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Release6)
     {
         return(Release6(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.ModeSense6)
     {
         return(ModeSense6((ModeSense6CommandDescriptorBlock)command, lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.ReadCapacity10)
     {
         return(ReadCapacity10(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Read6 ||
              command.OpCode == SCSIOpCodeName.Read10 ||
              command.OpCode == SCSIOpCodeName.Read16)
     {
         return(Read(command, lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Write6 ||
              command.OpCode == SCSIOpCodeName.Write10 ||
              command.OpCode == SCSIOpCodeName.Write16)
     {
         return(Write(command, lun, data, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.Verify10 ||
              command.OpCode == SCSIOpCodeName.Verify16)
     {
         return(Verify(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.SynchronizeCache10)
     {
         return(SynchronizeCache10(lun, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.ServiceActionIn &&
              command.ServiceAction == ServiceAction.ReadCapacity16)
     {
         uint allocationLength = command.TransferLength;
         return(ReadCapacity16(lun, allocationLength, out response));
     }
     else if (command.OpCode == SCSIOpCodeName.ReportLUNs)
     {
         return(ReportLUNs(out response));
     }
     else
     {
         ISCSIServer.Log("[ExecuteCommand] Unsupported SCSI Command (0x{0})", command.OpCode.ToString("X"));
         response = FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData());
         return(SCSIStatusCodeName.CheckCondition);
     }
 }