package org.jscsi.target.connection.stage.fullfeature; import java.io.IOException; import java.security.DigestException; import org.jscsi.exception.InternetSCSIException; import org.jscsi.parser.BasicHeaderSegment; import org.jscsi.parser.ProtocolDataUnit; import org.jscsi.parser.scsi.SCSICommandParser; import org.jscsi.target.connection.phase.TargetFullFeaturePhase; import org.jscsi.target.scsi.IResponseData; import org.jscsi.target.scsi.cdb.InquiryCDB; import org.jscsi.target.scsi.inquiry.PageCode.VitalProductDataPageName; import org.jscsi.target.scsi.inquiry.StandardInquiryData; import org.jscsi.target.scsi.inquiry.SupportedVpdPages; import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData; import org.jscsi.target.settings.SettingsException; import org.jscsi.target.util.Debug; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A stage for processing <code>INQUIRY</code> SCSI commands. * * @author Andreas Ergenzinger */ public class InquiryStage extends TargetFullFeatureStage { private static final Logger LOGGER = LoggerFactory.getLogger(InquiryStage.class); public InquiryStage(TargetFullFeaturePhase targetFullFeaturePhase) { super(targetFullFeaturePhase); } @Override public void execute(ProtocolDataUnit pdu) throws IOException, InterruptedException, InternetSCSIException, DigestException, SettingsException { final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment(); final SCSICommandParser parser = (SCSICommandParser)bhs.getParser(); ProtocolDataUnit responsePdu = null;// the response PDU // get command details in CDB if (LOGGER.isDebugEnabled()) {// print CDB bytes LOGGER.debug("CDB bytes: \n" + Debug.byteBufferToString(parser.getCDB())); } final InquiryCDB cdb = new InquiryCDB(parser.getCDB()); final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("cdb.getAllocationLength() = " + cdb.getAllocationLength()); LOGGER.debug("cdb.getEnableVitalProductData() = " + cdb.getEnableVitalProductData()); LOGGER.debug("cdb.isNormalACA() = " + cdb.isNormalACA()); LOGGER.debug("cdb.getPageCode() = " + cdb.getPageCode()); LOGGER.debug("cdb.getPageCode().getVitalProductDataPageName() = " + cdb.getPageCode().getVitalProductDataPageName()); } if (illegalFieldPointers != null) { // an illegal request has been made LOGGER.error("illegal INQUIRY request"); responsePdu = createFixedFormatErrorPdu(illegalFieldPointers, bhs.getInitiatorTaskTag(), parser .getExpectedDataTransferLength()); // send response connection.sendPdu(responsePdu); } else { // PDU is okay // carry out command IResponseData responseData = null; // "If the EVPD bit is set to zero, ... if (!cdb.getEnableVitalProductData()) { // ... the device server shall return the standard INQUIRY // data." responseData = StandardInquiryData.getInstance(); // TODO may need to set disk serial number } else { /* * SCSI initiator is requesting either "device identification" * or "supported VPD pages" or this else block would not have * been entered. (see {@link * InquiryCDB#checkIntegrity(ByteBuffer dataSegment)}) */ final VitalProductDataPageName pageName = cdb.getPageCode().getVitalProductDataPageName(); switch (pageName) {// is never null case SUPPORTED_VPD_PAGES: responseData = SupportedVpdPages.getInstance(); break; case DEVICE_IDENTIFICATION: responseData = session.getDeviceIdentificationVpdPage(); break; default: // The initiator must not request unsupported mode pages. throw new InternetSCSIException(); } } // send response sendResponse(bhs.getInitiatorTaskTag(), parser.getExpectedDataTransferLength(), responseData); } } }