summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/server/iscsi.h871
1 files changed, 869 insertions, 2 deletions
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index afbe60e..d0588e0 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -1070,6 +1070,771 @@ typedef struct __attribute__((packed)) iscsi_text_response_packet {
// B and C: Random
// D: Qualifier
+/* Only the following keys are used during the SecurityNegotiation stage
+ of the Login Phase (other keys MUST NOT be used):
+*/
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_SESSION_TYPE "SessionType" // Use: LO, Declarative, Any-Stage
+ // Senders: Initiator
+ // Scope: SW
+ // SessionType=<Discovery|Normal>
+ // Default is Normal.
+ // The initiator indicates the type of session it wants to create. The
+ // target can either accept it or reject it.
+ // A Discovery session indicates to the target that the only purpose of
+ // this session is discovery. The only requests a target accepts in
+ // this type of session are a Text Request with a SendTargets key and a
+ // Logout Request with reason "close the session".
+ // The Discovery session implies MaxConnections = 1 and overrides both
+ // the default and an explicit setting. ErrorRecoveryLevel MUST be 0
+ // (zero) for Discovery sessions.
+ // Depending on the type of session, a target may decide on resources to
+ // allocate, the security to enforce, etc., for the session. If the
+ // SessionType key is thus going to be offered as "Discovery", it SHOULD
+ // be offered in the initial Login Request by the initiator
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_INITIATOR_NAME "InitiatorName" // Use: IO, Declarative, Any-Stage
+ // Senders: Initiator
+ // Scope: SW
+ // InitiatorName=<iSCSI-name-value>
+ // Examples:
+ // InitiatorName=iqn.1992-04.de.uni-freiburg.bwlehrpool:qcow2.5003
+ // InitiatorName=iqn.2001-02.de.uni-freiburg.matrix:basty.eduroam
+ // InitiatorName=naa.52004567BA64678D
+ // The initiator of the TCP connection MUST provide this key to the
+ // remote endpoint at the first login of the Login Phase for every
+ // connection. The InitiatorName key enables the initiator to identify
+ // itself to the remote endpoint.
+ // The InitiatorName MUST NOT be redeclared within the Login Phase
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_TARGET_NAME "TargetName" // Use: IO by initiator, FFPO by target - only as response to a
+ // SendTargets, Declarative, Any-Stage
+ // Senders: Initiator and target
+ // Scope: SW
+ // TargetName=<iSCSI-name-value>
+ // Examples:
+ // TargetName=iqn.1993-11.de.uni-freiburg:diskarrays.sn.5003
+ // TargetName=eui.020000023B040506
+ // TargetName=naa.62004567BA64678D0123456789ABCDEF
+ // The initiator of the TCP connection MUST provide this key to the
+ // remote endpoint in the first Login Request if the initiator is not
+ // establishing a Discovery session. The iSCSI Target Name specifies
+ // the worldwide unique name of the target.
+ // The TargetName key may also be returned by the SendTargets Text
+ // Request (which is its only use when issued by a target).
+ // The TargetName MUST NOT be redeclared within the Login Phase
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_TARGET_ADDRESS "TargetAddress" // Use: ALL, Declarative, Any-Stage
+ // Senders: Target
+ // Scope: SW
+ // TargetAddress=domainname[:port][,portal-group-tag]
+ // The domainname can be specified as either a DNS host name, a dotted-
+ // decimal IPv4 address, or a bracketed IPv6 address as specified in
+ // RFC3986.
+ // If the TCP port is not specified, it is assumed to be the IANA-
+ // assigned default port for iSCSI.
+ // If the TargetAddress is returned as the result of a redirect status
+ // in a Login Response, the comma and portal-group-tag MUST be omitted.
+ // If the TargetAddress is returned within a SendTargets response, the
+ // portal-group-tag MUST be included.
+ // Examples:
+ // TargetAddress=10.0.0.1:5003,1
+ // TargetAddress=[1080:0:0:0:8:800:200C:417A],65
+ // TargetAddress=[1080::8:800:200C:417A]:5003,1
+ // TargetAddress=gitlab.uni-freiburg.de,443
+ // The formats for the port and portal-group-tag are the same as the one
+ // specified in TargetPortalGroupTag
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_INITIATOR_ALIAS "InitiatorAlias" // Use: ALL, Declarative, Any-Stage
+ // Senders: Initiator
+ // Scope: SW
+ // InitiatorAlias=<iSCSI-local-name-value>
+ // Examples:
+ // InitiatorAlias=Web Server 5
+ // InitiatorAlias=matrix.uni-freiburg.de
+ // InitiatorAlias=Matrix Server
+ // If an initiator has been configured with a human-readable name or
+ // description, it SHOULD be communicated to the target during a Login
+ // Request PDU. If not, the host name can be used instead. This string
+ // is not used as an identifier, nor is it meant to be used for
+ // authentication or authorization decisions. It can be displayed by
+ // the target's user interface in a list of initiators to which it is
+ // connected
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_TARGET_ALIAS "TargetAlias" // Use: ALL, Declarative, Any-Stage
+ // Senders: Target
+ // Scope: SW
+ // TargetAlias=<iSCSI-local-name-value>
+ // Examples:
+ // TargetAlias=Bob-s Disk
+ // TargetAlias=Database Server 1 Log Disk
+ // TargetAlias=Web Server 3 Disk 20
+ // If a target has been configured with a human-readable name or
+ // description, this name SHOULD be communicated to the initiator during
+ // a Login Response PDU if SessionType=Normal. This string is not used
+ // as an identifier, nor is it meant to be used for authentication or
+ // authorization decisions. It can be displayed by the initiator's user
+ // interface in a list of targets to which it is connected
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_TARGET_PORTAL_GROUP_TAG "TargetPortalGroupTag" // Use: IO by target, Declarative, Any-Stage
+ // Senders: Target
+ // Scope: SW
+ // TargetPortalGroupTag=<16-bit-binary-value>
+ // Example:
+ // TargetPortalGroupTag=1
+ // The TargetPortalGroupTag key is a 16-bit binary-value that uniquely
+ // identifies a portal group within an iSCSI target node. This key
+ // carries the value of the tag of the portal group that is servicing
+ // the Login Request. The iSCSI target returns this key to the
+ // initiator in the Login Response PDU to the first Login Request PDU
+ // that has the C bit set to 0 when TargetName is given by the
+ // initiator.
+ // SAM2 notes in its informative text that the TPGT value should be
+ // non-zero; note that this is incorrect. A zero value is allowed as a
+ // legal value for the TPGT. This discrepancy currently stands
+ // corrected in SAM4
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD "AuthMethod" // Use: During Login - Security Negotiation
+ // Senders: Initiator and target
+ // Scope: connection
+ // AuthMethod = <list-of-values>
+ // The main item of security negotiation is the authentication method
+ // (AuthMethod).
+ // The authentication methods that can be used (appear in the list-of-
+ // values) are either vendor-unique methods or those listed in the
+ // following table:
+ // +--------------------------------------------------------------+
+ // | Name | Description |
+ // +--------------------------------------------------------------+
+ // | KRB5 | Kerberos V5 - defined in RFC4120 |
+ // +--------------------------------------------------------------+
+ // | SRP | Secure Remote Password - |
+ // | | defined in RFC2945 |
+ // +--------------------------------------------------------------+
+ // | CHAP | Challenge Handshake Authentication Protocol - |
+ // | | defined in RFC1994 |
+ // +--------------------------------------------------------------+
+ // | None | No authentication |
+ // +--------------------------------------------------------------+
+ // The AuthMethod selection is followed by an "authentication exchange"
+ // specific to the authentication method selected.
+ // The authentication method proposal may be made by either the
+ // initiator or the target. However, the initiator MUST make the first
+ // step specific to the selected authentication method as soon as it is
+ // selected. It follows that if the target makes the authentication
+ // method proposal, the initiator sends the first key(s) of the exchange
+ // together with its authentication method selection.
+ // The authentication exchange authenticates the initiator to the target
+ // and, optionally, the target to the initiator. Authentication is
+ // OPTIONAL to use but MUST be supported by the target and initiator.
+ // The initiator and target MUST implement CHAP. All other
+ // authentication methods are OPTIONAL.
+ // Private or public extension algorithms MAY also be negotiated for
+ // authentication methods. Whenever a private or public extension
+ // algorithm is part of the default offer (the offer made in the absence
+ // of explicit administrative action), the implementer MUST ensure that
+ // CHAP is listed as an alternative in the default offer and "None" is
+ // not part of the default offer.
+ // Extension authentication methods MUST be named using one of the
+ // following two formats:
+ // 1) Z-reversed.vendor.dns_name.do_something=
+ // 2) New public key with no name prefix constraints
+ // Authentication methods named using the Z- format are used as private
+ // extensions. New public keys must be registered with IANA using the
+ // IETF Review process RFC5226. New public extensions for
+ // authentication methods MUST NOT use the Z# name prefix.
+ // For all of the public or private extension authentication methods,
+ // the method-specific keys MUST conform to the format specified for
+ // standard-label.
+ // To identify the vendor for private extension authentication methods,
+ // we suggest using the reversed DNS-name as a prefix to the proper
+ // digest names.
+ // The part of digest-name following Z- MUST conform to the format for
+ // standard-label.
+ // Support for public or private extension authentication methods is
+ // OPTIONAL
+
+/* Kerberos V5 (KRB5) related authentication keys: */
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_KRB_AP_REQ "KRB_AP_REQ" // For KRB5 (Kerberos V5) (see RFC4120 and RFC1964), the initiator MUST use:
+ // KRB_AP_REQ=<KRB_AP_REQ>
+ // where KRB_AP_REQ is the client message as defined in RFC4120.
+ // The default principal name assumed by an iSCSI initiator or target
+ // (prior to any administrative configuration action) MUST be the iSCSI
+ // Initiator Name or iSCSI Target Name, respectively, prefixed by the
+ // string "iscsi/".
+ // If the initiator authentication fails, the target MUST respond with a
+ // Login reject with "Authentication Failure" status. Otherwise, if the
+ // initiator has selected the mutual authentication option (by setting
+ // MUTUAL-REQUIRED in the ap-options field of the KRB_AP_REQ), the
+ // target MUST reply with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_KRB_AP_REP "KRB_AP_REP" // KRB_AP_REP=<KRB_AP_REP>
+ // where KRB_AP_REP is the server's response message as defined in
+ // RFC4120.
+ // If mutual authentication was selected and target authentication
+ // fails, the initiator MUST close the connection.
+ // KRB_AP_REQ and KRB_AP_REP are binary-values, and their binary length
+ // (not the length of the character string that represents them in
+ // encoded form) MUST NOT exceed 65536 bytes. Hex or Base64 encoding
+ // may be used for KRB_AP_REQ and KRB_AP_REP
+
+/* Secure Remote Password (SRP) related authentication keys: */
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_U "SRP_U" // For SRP RFC2945, the initiator MUST use:
+ // SRP_U=<U> TargetAuth=Yes or TargetAuth=No
+ // The target MUST answer with a Login reject with the "Authorization
+ // Failure" status or reply with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_GROUP "SRP_GROUP" // SRP_GROUP=<G1,G2...> SRP_s=<s>
+ // where G1,G2... are proposed groups, in order of preference.
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_A "SRP_A" // The initiator MUST either close the connection or continue with:
+ // SRP_A=<A>
+ // SRP_GROUP=<G>
+ // where G is one of G1,G2... that were proposed by the target.
+ // The target MUST answer with a Login reject with the "Authentication
+ // Failure" status or reply with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_B "SRP_B" // SRP_B=<B>
+ // The initiator MUST close the connection or continue with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_M "SRP_M" // SRP_M=<M>
+ // If the initiator authentication fails, the target MUST answer with a
+ // Login reject with "Authentication Failure" status. Otherwise, if the
+ // initiator sent TargetAuth=Yes in the first message (requiring target
+ // authentication), the target MUST reply with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_SRP_SRP_HM "SRP_HM" // SRP_HM=<H(A | M | K)>
+ // If the target authentication fails, the initiator MUST close the
+ // connection:
+ // where U, s, A, B, M, and H(A | M | K) are defined in RFC2945 (using
+ // the SHA1 hash function, such as SRP-SHA1) and
+ // G,Gn ("Gn" stands for G1,G2...) are identifiers of SRP groups
+ // specified in RFC3723.
+ // G, Gn, and U are text strings; s,A,B,M, and H(A | M | K) are
+ // binary-values. The length of s,A,B,M and H(A | M | K) in binary form
+ // (not the length of the character string that represents them in
+ // encoded form) MUST NOT exceed 1024 bytes. Hex or Base64 encoding may
+ // be used for s,A,B,M and H(A | M | K).
+ // For the SRP_GROUP, all the groups specified in RFC3723 up to
+ // 1536 bits (i.e. SRP-768, SRP-1024, SRP-1280, SRP-1536) must be
+ // supported by initiators and targets. To guarantee interoperability,
+ // targets MUST always offer "SRP-1536" as one of the proposed groups
+
+/* Challenge Handshake Authentication Protocol (CHAP) related authentication keys: */
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_CHAP_CHAP_A "CHAP_A" // For CHAP RFC1994, the initiator MUST use:
+ // CHAP_A=<A1,A2...>
+ // where A1,A2... are proposed algorithms, in order of preference.
+ // The target MUST answer with a Login reject with the "Authentication
+ // Failure" status or reply with:
+ // CHAP_A=<A>
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_CHAP_CHAP_I "CHAP_I" // CHAP_I=<I>
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_CHAP_CHAP_C "CHAP_C" // CHAP_C=<C>
+ // where A is one of A1,A2... that were proposed by the initiator.
+ // The initiator MUST continue with:
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_CHAP_CHAP_N "CHAP_N" // CHAP_N=<N>
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_AUTH_METHOD_CHAP_CHAP_R "CHAP_R" // CHAP_R=<R>
+ // or, if it requires target authentication, with:
+ // CHAP_N=<N>
+ // CHAP_R=<R>
+ // CHAP_I=<I>
+ // CHAP_C=<C>
+ // If the initiator authentication fails, the target MUST answer with a
+ // Login reject with "Authentication Failure" status. Otherwise, if the
+ // initiator required target authentication, the target MUST either
+ // answer with a Login reject with "Authentication Failure" or reply
+ // with:
+ // CHAP_N=<N>
+ // CHAP_R=<R>
+ // If the target authentication fails, the initiator MUST close the
+ // connection:
+ // where N, (A,A1,A2), I, C, and R are (correspondingly) the Name,
+ // Algorithm, Identifier, Challenge, and Response as defined in
+ // RFC1994.
+ // N is a text string; A,A1,A2, and I are numbers; C and R are
+ // binary-values. Their binary length (not the length of the character
+ // string that represents them in encoded form) MUST NOT exceed
+ // 1024 bytes. Hex or Base64 encoding may be used for C and R.
+ // For the Algorithm, as stated in [RFC1994], one value is required to
+ // be implemented:
+ // 5 (CHAP with MD5)
+ // To guarantee interoperability, initiators MUST always offer it as one
+ // of the proposed algorithms
+
+/* Login/Text Operational Text Keys
+
+ Some session-specific parameters MUST only be carried on the leading
+ connection and cannot be changed after the leading connection login
+ (e.g., MaxConnections - the maximum number of connections). This
+ holds for a single connection session with regard to connection
+ restart. The keys that fall into this category have the "use: LO"
+ (Leading Only).
+
+ Keys that can only be used during login have the "use: IO"
+ (Initialize Only), while those that can be used in both the Login
+ Phase and Full Feature Phase have the "use: ALL".
+
+ Keys that can only be used during the Full Feature Phase use FFPO
+ (Full Feature Phase Only).
+
+ Keys marked as Any-Stage may also appear in the SecurityNegotiation
+ stage, while all other keys described in this section are
+ operational keys.
+
+ Keys that do not require an answer are marked as Declarative.
+
+ Key scope is indicated as session-wide (SW) or connection-only (CO).
+
+ "Result function", wherever mentioned, states the function that can
+ be applied to check the validity of the responder selection.
+ "Minimum" means that the selected value cannot exceed the offered
+ value. "Maximum" means that the selected value cannot be lower than
+ the offered value. "AND" means that the selected value must be a
+ possible result of a Boolean "and" function with an arbitrary Boolean
+ value (e.g., if the offered value is No the selected value must be
+ No). "OR" means that the selected value must be a possible result of
+ a Boolean "or" function with an arbitrary Boolean value (e.g., if the
+ offered value is Yes the selected value must be Yes).
+*/
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_HEADER_DIGEST "HeaderDigest" // Use: IO
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_DATA_DIGEST "DataDigest" // Senders: Initiator and target
+ // Scope: CO
+ // HeaderDigest = <list-of-values>
+ // DataDigest = <list-of-values>
+ // Default is None for both HeaderDigest and DataDigest.
+ // Digests enable the checking of end-to-end, non-cryptographic data
+ // integrity beyond the integrity checks provided by the link layers and
+ // the covering of the whole communication path, including all elements
+ // that may change the network-level PDUs, such as routers, switches,
+ // and proxies.
+ // The following table lists cyclic integrity checksums that can be
+ // negotiated for the digests and MUST be implemented by every iSCSI
+ // initiator and target. These digest options only have error detection
+ // significance.
+ // +---------------------------------------------+
+ // | Name | Description | Generator |
+ // +---------------------------------------------+
+ // | CRC32C | 32-bit CRC |0x11edc6f41|
+ // +---------------------------------------------+
+ // | None | no digest |
+ // +---------------------------------------------+
+ // The generator polynomial G(x) for this digest is given in hexadecimal
+ // notation (e.g. "0x3b" stands for 0011 1011, and the polynomial is
+ // x**5 + x**4 + x**3 + x + 1).
+ // When the initiator and target agree on a digest, this digest MUST be
+ // used for every PDU in the Full Feature Phase.
+ // Padding bytes, when present in a segment covered by a CRC, SHOULD be
+ // set to 0 and are included in the CRC.
+ // The CRC MUST be calculated by a method that produces the same results
+ // as the following process:
+ // - The PDU bits are considered as the coefficients of a polynomial
+ // M(x) of degree n - 1; bit 7 of the lowest numbered byte is
+ // considered the most significant bit (x**n - 1), followed by bit 6
+ // of the lowest numbered byte through bit 0 of the highest numbered
+ // byte (x**0).
+ // - The most significant 32 bits are complemented.
+ // - The polynomial is multiplied by x**32, then divided by G(x). The
+ // generator polynomial produces a remainder R(x) of degree <= 31.
+ // - The coefficients of R(x) are formed into a 32-bit sequence.
+ // - The bit sequence is complemented, and the result is the CRC.
+ // - The CRC bits are mapped into the digest word. The x**31
+ // coefficient is mapped to bit 7 of the lowest numbered byte of the
+ // digest, and the mapping continues with successive coefficients and
+ // bits so that the x**24 coefficient is mapped to bit 0 of the lowest
+ // numbered byte. The mapping continues further with the x**23
+ // coefficient mapped to bit 7 of the next byte in the digest until
+ // the x**0 coefficient is mapped to bit 0 of the highest numbered
+ // byte of the digest.
+ // - Computing the CRC over any segment (data or header) extended to
+ // include the CRC built using the generator 0x11edc6f41 will always
+ // get the value 0x1c2d19ed as its final remainder (R(x)). This value
+ // is given here in its polynomial form (i.e., not mapped as the
+ // digest word).
+ // For a discussion about selection criteria for the CRC, see RFC3385.
+ // For a detailed analysis of the iSCSI polynomial, see Castagnoli93.
+ // Private or public extension algorithms MAY also be negotiated for
+ // digests. Whenever a private or public digest extension algorithm is
+ // part of the default offer (the offer made in the absence of explicit
+ // administrative action), the implementer MUST ensure that CRC32C is
+ // listed as an alternative in the default offer and "None" is not part
+ // of the default offer.
+ // Extension digest algorithms MUST be named using one of the following
+ // two formats:
+ // 1) Y-reversed.vendor.dns_name.do_something=
+ // 2) New public key with no name prefix constraints
+ // Digests named using the Y- format are used for private purposes
+ // (unregistered). New public keys must be registered with IANA using
+ // the IETF Review process (RFC5226). New public extensions for
+ // digests MUST NOT use the Y# name prefix.
+ // For private extension digests, to identify the vendor we suggest
+ // using the reversed DNS-name as a prefix to the proper digest names.
+ // The part of digest-name following Y- MUST conform to the format for
+ // standard-label specified.
+ // Support for public or private extension digests is OPTIONA
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_MAX_CONNECTIONS "MaxConnections" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // MaxConnections=<numerical-value-from-1-to-65535>
+ // Default is 1.
+ // Result function is Minimum.
+ // The initiator and target negotiate the maximum number of connections
+ // requested/acceptable
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_SEND_TARGETS "SendTargets" // Use: FFPO
+ // Senders: Initiator
+ // Scope: SW
+ // The text in this appendix is a normative part of this document.
+ // To reduce the amount of configuration required on an initiator, iSCSI
+ // provides the SendTargets Text Request. The initiator uses the
+ // SendTargets request to get a list of targets to which it may have
+ // access, as well as the list of addresses (IP address and TCP port) on
+ // which these targets may be accessed.
+ // To make use of SendTargets, an initiator must first establish one of
+ // two types of sessions. If the initiator establishes the session
+ // using the key "SessionType=Discovery", the session is a Discovery
+ // session, and a target name does not need to be specified. Otherwise,
+ // the session is a Normal operational session. The SendTargets command
+ // MUST only be sent during the Full Feature Phase of a Normal or
+ // Discovery session.
+ // A system that contains targets MUST support Discovery sessions on
+ // each of its iSCSI IP address-port pairs and MUST support the
+ // SendTargets command on the Discovery session. In a Discovery
+ // session, a target MUST return all path information (IP address-port
+ // pairs and Target Portal Group Tags) for the targets on the target
+ // Network Entity that the requesting initiator is authorized to access.
+ // A target MUST support the SendTargets command on operational
+ // sessions; these will only return path information about the target to
+ // which the session is connected and do not need to return information
+ // about other target names that may be defined in the responding
+ // system.
+ // An initiator MAY make use of the SendTargets command as it sees fit.
+ // A SendTargets command consists of a single Text Request PDU. This
+ // PDU contains exactly one text key and value. The text key MUST be
+ // SendTargets. The expected response depends upon the value, as well
+ // as whether the session is a Discovery session or an operational
+ // session.
+ // The value must be one of:
+ // All
+ // The initiator is requesting that information on all relevant
+ // targets known to the implementation be returned. This value
+ // MUST be supported on a Discovery session and MUST NOT be
+ // supported on an operational session.
+ // <iSCSI-target-name>
+ // If an iSCSI Target Name is specified, the session should
+ // respond with addresses for only the named target, if possible.
+ // This value MUST be supported on Discovery sessions. A
+ // Discovery session MUST be capable of returning addresses for
+ // those targets that would have been returned had value=All been
+ // designated.
+ // <nothing>
+ // The session should only respond with addresses for the target
+ // to which the session is logged in. This MUST be supported on
+ // operational sessions and MUST NOT return targets other than the
+ // one to which the session is logged in.
+ // The response to this command is a Text Response that contains a list
+ // of zero or more targets and, optionally, their addresses. Each
+ // target is returned as a target record. A target record begins with
+ // the TargetName text key, followed by a list of TargetAddress text
+ // keys, and bounded by the end of the Text Response or the next
+ // TargetName key, which begins a new record. No text keys other than
+ // TargetName and TargetAddress are permitted within a SendTargets
+ // response.
+ // A Discovery session MAY respond to a SendTargets request with its
+ // complete list of targets, or with a list of targets that is based on
+ // the name of the initiator logged in to the session.
+ // A SendTargets response MUST NOT contain target names if there are no
+ // targets for the requesting initiator to access.
+ // Each target record returned includes zero or more TargetAddress
+ // fields.
+ // Each target record starts with one text key of the form:
+ // TargetName=<target-name-goes-here>
+ // followed by zero or more address keys of the form:
+ // TargetAddress=<hostname-or-ipaddress>[:<tcp-port>],
+ // <portal-group-tag>
+ // The hostname-or-ipaddress contains a domain name, IPv4 address, or
+ // IPv6 address (RFC4291), as specified for the TargetAddress key.
+ // A hostname-or-ipaddress duplicated in TargetAddress responses for a
+ // given node (the port is absent or equal) would probably indicate that
+ // multiple address families are in use at once (IPv6 and IPv4).
+ // Each TargetAddress belongs to a portal group, identified by its
+ // numeric Target Portal Group Tag. The iSCSI Target
+ // Name, together with this tag, constitutes the SCSI port identifier;
+ // the tag only needs to be unique within a given target's name list of
+ // addresses.
+ // Multiple-connection sessions can span iSCSI addresses that belong to
+ // the same portal group.
+ // Multiple-connection sessions cannot span iSCSI addresses that belong
+ // to different portal groups.
+ // If a SendTargets response reports an iSCSI address for a target, it
+ // SHOULD also report all other addresses in its portal group in the
+ // same response.
+ // A SendTargets Text Response can be longer than a single Text Response
+ // PDU and makes use of the long Text Responses as specified.
+ // After obtaining a list of targets from the Discovery session, an
+ // iSCSI initiator may initiate new sessions to log in to the discovered
+ // targets for full operation. The initiator MAY keep the Discovery
+ // session open and MAY send subsequent SendTargets commands to discover
+ // new targets.
+ // Examples:
+ // This example is the SendTargets response from a single target that
+ // has no other interface ports.
+ // The initiator sends a Text Request that contains:
+ // SendTargets=All
+ // The target sends a Text Response that contains:
+ // TargetName=iqn.1993-11.de.uni-freiburg:diskarray.sn.8675309
+ // All the target had to return in this simple case was the target name.
+ // It is assumed by the initiator that the IP address and TCP port for
+ // this target are the same as those used on the current connection to
+ // the default iSCSI target.
+ // The next example has two internal iSCSI targets, each accessible via
+ // two different ports with different IP addresses. The following is
+ // the Text Response:
+ // TargetName=iqn.1993-11.de.uni-freiburg:diskarray.sn.8675309
+ // TargetAddress=10.1.0.45:5300,1
+ // TargetAddress=10.1.1.45:5300,2
+ // TargetName=iqn.1993-11.de.uni-freiburg:diskarray.sn.1234567
+ // TargetAddress=10.1.0.45:5300,1
+ // TargetAddress=10.1.1.45:5300,2
+ // Both targets share both addresses; the multiple addresses are likely
+ // used to provide multi-path support. The initiator may connect to
+ // either target name on either address. Each of the addresses has its
+ // own Target Portal Group Tag; they do not support spanning multiple-
+ // connection sessions with each other. Keep in mind that the Target
+ // Portal Group Tags for the two named targets are independent of one
+ // another; portal group "1" on the first target is not necessarily the
+ // same as portal group "1" on the second target.
+ // In the above example, a DNS host name or an IPv6 address could have
+ // been returned instead of an IPv4 address.
+ // The next Text Response shows a target that supports spanning sessions
+ // across multiple addresses and further illustrates the use of the
+ // Target Portal Group Tags:
+ // TargetName=iqn.1993-11.de.uni-freiburg:diskarray.sn.8675309
+ // TargetAddress=10.1.0.45:5300,1
+ // TargetAddress=10.1.1.46:5300,1
+ // TargetAddress=10.1.0.47:5300,2
+ // TargetAddress=10.1.1.48:5300,2
+ // TargetAddress=10.1.1.49:5300,3
+ // In this example, any of the target addresses can be used to reach the
+ // same target. A single-connection session can be established to any
+ // of these TCP addresses. A multiple-connection session could span
+ // addresses .45 and .46 or .47 and .48 but cannot span any other
+ // combination. A TargetAddress with its own tag (.49) cannot be
+ // combined with any other address within the same session.
+ // This SendTargets response does not indicate whether .49 supports
+ // multiple connections per session; it is communicated via the
+ // MaxConnections text key upon login to the target
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_INITIAL_R2T "InitialR2T" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // InitialR2T=<boolean-value>
+ // Examples:
+ // I->InitialR2T=No
+ // T->InitialR2T=No
+ // Default is Yes.
+ // Result function is OR.
+ // The InitialR2T key is used to turn off the default use of R2T for
+ // unidirectional operations and the output part of bidirectional
+ // commands, thus allowing an initiator to start sending data to a
+ // target as if it has received an initial R2T with Buffer
+ // Offset=Immediate Data Length and Desired Data Transfer
+ // Length=(min(FirstBurstLength, Expected Data Transfer Length) -
+ // Received Immediate Data Length).
+ // The default action is that R2T is required, unless both the initiator
+ // and the target send this key-pair attribute specifying InitialR2T=No.
+ // Only the first outgoing data burst (immediate data and/or separate
+ // PDUs) can be sent unsolicited (i.e., not requiring an explicit R2T)
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_IMMEDIATE_DATA "ImmediateData" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // ImmediateData=<boolean-value>
+ // Default is Yes.
+ // Result function is AND.
+ // The initiator and target negotiate support for immediate dataTo
+ // turn immediate data off, the initiator or target must state its
+ // desire to do soImmediateData can be turned on if both the
+ // initiator and target have ImmediateData=Yes.
+ // If ImmediateData is set to Yes and InitialR2T is set to Yes
+ // (default), then only immediate data are accepted in the first burst.
+ // If ImmediateData is set to No and InitialR2T is set to Yes, then the
+ // initiator MUST NOT send unsolicited data and the target MUST reject
+ // unsolicited data with the corresponding response code.
+ // If ImmediateData is set to No and InitialR2T is set to No, then the
+ // initiator MUST NOT send unsolicited immediate data but MAY send one
+ // unsolicited burst of Data-OUT PDUs.
+ // If ImmediateData is set to Yes and InitialR2T is set to No, then the
+ // initiator MAY send unsolicited immediate data and/or one unsolicited
+ // burst of Data-OUT PDUs.
+ // The following table is a summary of unsolicited data options:
+ // +----------+-------------+------------------+-------------+
+ // |InitialR2T|ImmediateData| Unsolicited |ImmediateData|
+ // | | | Data-Out PDUs | |
+ // +----------+-------------+------------------+-------------+
+ // | No | No | Yes | No |
+ // +----------+-------------+------------------+-------------+
+ // | No | Yes | Yes | Yes |
+ // +----------+-------------+------------------+-------------+
+ // | Yes | No | No | No |
+ // +----------+-------------+------------------+-------------+
+ // | Yes | Yes | No | Yes |
+ // +----------+-------------+------------------+-------------+
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_MAX_RECV_DS_LEN "MaxRecvDataSegmentLength" // Use: ALL, Declarative
+ // Senders: Initiator and target
+ // Scope: CO
+ // MaxRecvDataSegmentLength=<numerical-value-512-to-(2**24 - 1)>
+ // Default is 8192 bytes.
+ // The initiator or target declares the maximum data segment length in
+ // bytes it can receive in an iSCSI PDU.
+ // The transmitter (initiator or target) is required to send PDUs with a
+ // data segment that does not exceed MaxRecvDataSegmentLength of the
+ // receiver.
+ // A target receiver is additionally limited by MaxBurstLength for
+ // solicited data and FirstBurstLength for unsolicited dataAn
+ // initiator MUST NOT send solicited PDUs exceeding MaxBurstLength nor
+ // unsolicited PDUs exceeding FirstBurstLength (or FirstBurstLength-
+ // Immediate Data Length if immediate data were sent)
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_MAX_BURST_LEN "MaxBurstLength" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // MaxBurstLength=<numerical-value-512-to-(2**24 - 1)>
+ // Default is 262144 (256 KB).
+ // Result function is Minimum.
+ // The initiator and target negotiate the maximum SCSI data payload in
+ // bytes in a Data-In or a solicited Data-Out iSCSI sequence. A
+ // sequence consists of one or more consecutive Data-In or Data-Out PDUs
+ // that end with a Data-In or Data-Out PDU with the F bit set to 1
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_FIRST_BURST_LEN "FirstBurstLength" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // Irrelevant when: ( InitialR2T=Yes and ImmediateData=No )
+ // FirstBurstLength=<numerical-value-512-to-(2**24 - 1)>
+ // Default is 65536 (64 KB).
+ // Result function is Minimum.
+ // The initiator and target negotiate the maximum amount in bytes of
+ // unsolicited data an iSCSI initiator may send to the target during the
+ // execution of a single SCSI command. This covers the immediate data
+ // (if any) and the sequence of unsolicited Data-Out PDUs (if any) that
+ // follow the command.
+ // FirstBurstLength MUST NOT exceed MaxBurstLength
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_DEFAULT_TIME_WAIT "DefaultTime2Wait" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // DefaultTime2Wait=<numerical-value-0-to-3600>
+ // Default is 2.
+ // Result function is Maximum.
+ // The initiator and target negotiate the minimum time, in seconds, to
+ // wait before attempting an explicit/implicit logout or an active task
+ // reassignment after an unexpected connection termination or a
+ // connection reset.
+ // A value of 0 indicates that logout or active task reassignment can be
+ // attempted immediately
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_DEFAULT_TIME_RETAIN "DefaultTime2Retain" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // DefaultTime2Retain=<numerical-value-0-to-3600>
+ // Default is 20.
+ // Result function is Minimum.
+ // The initiator and target negotiate the maximum time, in seconds,
+ // after an initial wait (Time2Wait), before which an active task
+ // reassignment is still possible after an unexpected connection
+ // termination or a connection reset.
+ // This value is also the session state timeout if the connection in
+ // question is the last LOGGED_IN connection in the session.
+ // A value of 0 indicates that connection/task state is immediately
+ // discarded by the target
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_MAX_OUTSTANDING_R2T "MaxOutstandingR2T" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // MaxOutstandingR2T=<numerical-value-from-1-to-65535>
+ // Irrelevant when: SessionType=Discovery
+ // Default is 1.
+ // Result function is Minimum.
+ // The initiator and target negotiate the maximum number of outstanding
+ // R2Ts per task, excluding any implied initial R2T that might be part
+ // of that task. An R2T is considered outstanding until the last data
+ // PDU (with the F bit set to 1) is transferred or a sequence reception
+ // timeout is encountered for that data sequence
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_DATA_PDU_IN_ORDER "DataPDUInOrder" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // DataPDUInOrder=<boolean-value>
+ // Default is Yes.
+ // Result function is OR.
+ // "No" is used by iSCSI to indicate that the data PDUs within sequences
+ // can be in any order. "Yes" is used to indicate that data PDUs within
+ // sequences have to be at continuously increasing addresses and
+ // overlays are forbidden
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_DATA_SEQ_IN_ORDER "DataSequenceInOrder" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // DataSequenceInOrder=<boolean-value>
+ // Default is Yes.
+ // Result function is OR.
+ // A data sequence is a sequence of Data-In or Data-Out PDUs that end
+ // with a Data-In or Data-Out PDU with the F bit set to 1. A Data-Out
+ // sequence is sent either unsolicited or in response to an R2T.
+ // Sequences cover an offset-range.
+ // If DataSequenceInOrder is set to No, data PDU sequences may be
+ // transferred in any order.
+ // If DataSequenceInOrder is set to Yes, data sequences MUST be
+ // transferred using continuously non-decreasing sequence offsets (R2T
+ // buffer offset for writes, or the smallest SCSI Data-In buffer offset
+ // within a read data sequence).
+ // If DataSequenceInOrder is set to Yes, a target may retry at most the
+ // last R2T, and an initiator may at most request retransmission for the
+ // last read data sequence. For this reason, if ErrorRecoveryLevel is
+ // not 0 and DataSequenceInOrder is set to Yes, then MaxOutstandingR2T
+ // MUST be set to 1
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_ERR_RECOVERY_LEVEL "ErrorRecoveryLevel" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // ErrorRecoveryLevel=<numerical-value-0-to-2>
+ // Default is 0.
+ // Result function is Minimum.
+ // The initiator and target negotiate the recovery level supported.
+ // Recovery levels represent a combination of recovery capabilities.
+ // Each recovery level includes all the capabilities of the lower
+ // recovery levels and adds some new ones to them.
+ // In the description of recovery mechanisms, certain recovery classes
+ // are specified
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_PRIV_EXT_KEY_FMT "X-reversed.vendor" // Use: ALL
+ // Senders: Initiator and target
+ // Scope: specific key dependent
+ // X-reversed.vendor.dns_name.do_something=
+ // Keys with this format are used for private extension purposes. These
+ // keys always start with X- if unregistered with IANA (private). New
+ // public keys (if registered with IANA via an IETF Review RFC5226) no
+ // longer have an X# name prefix requirement; implementers may propose
+ // any intuitive unique name.
+ // For unregistered keys, to identify the vendor we suggest using the
+ // reversed DNS-name as a prefix to the key-proper.
+ // The part of key-name following X- MUST conform to the format for
+ // key-name.
+ // Vendor-specific keys MUST ONLY be used in Normal sessions.
+ // Support for public or private extension keys is OPTIONAL
+#define ISCSI_LOGIN_AUTH_TEXT_KEY_TASK_REPORTING "TaskReporting" // Use: LO
+ // Senders: Initiator and target
+ // Scope: SW
+ // Irrelevant when: SessionType=Discovery
+ // TaskReporting=<list-of-values>
+ // Default is RFC3720.
+ // This key is used to negotiate the task completion reporting semantics
+ // from the SCSI target. The following table describes the semantics
+ // that an iSCSI target MUST support for respective negotiated key
+ // values. Whenever this key is negotiated, at least the RFC3720 and
+ // ResponseFence values MUST be offered as options by the negotiation
+ // originator.
+ // +--------------+------------------------------------------+
+ // | Name | Description |
+ // +--------------+------------------------------------------+
+ // | RFC3720 | RFC 3720-compliant semantics. Response |
+ // | | fencing is not guaranteed, and fast |
+ // | | completion of multi-task aborting is not |
+ // | | supported. |
+ // +--------------+------------------------------------------+
+ // | ResponseFence| Response Fence |
+ // | | semantics MUST be supported in reporting |
+ // | | task completions. |
+ // +--------------+------------------------------------------+
+ // | FastAbort | Updated fast multi-task abort semantics |
+ // | | defined in MUST be supported. Support |
+ // | | for the Response. Fence is implied - |
+ // | | i.e., semantics MUST be supported as |
+ // | | well. |
+ // +--------------+------------------------------------------+
+ // When TaskReporting is not negotiated to FastAbort, the
+ // standard multi-task abort semantics MUST be used
+
/* This is an initiator-defined component of the session identifier and
is structured as follows:
@@ -1424,7 +2189,7 @@ typedef struct __attribute__((packed)) iscsi_login_response_packet {
been delivered to SCSI because one or more commands with a smaller
CmdSN have not been received by iSCSI. The resulting holes in the
command sequence numbers will have to be handled by appropriate
- recovery (see Section 7), unless the session is also closed.
+ recovery, unless the session is also closed.
*/
typedef struct __attribute__((packed)) iscsi_logout_req_packet {
uint8_t opcode; // Always 0x06 according to specification (see above)
@@ -1718,9 +2483,111 @@ typedef struct __attribute__((packed)) iscsi_reject_packet {
// task, if any
uint32_t reserved5[2]; // Reserved for future usage
struct iscsi_header_digest hdr_digest; // Optional header digest
- struct iscsi_bhs_packet bad_pdu_hdr; // Complete Header of Bad PDU
+ struct iscsi_bhs_packet bad_pdu_hdr; // Complete Header of Bad PDU. The target returns the
+ // header (not including the digest) of the PDU in error
+ // as the data of the response
uint8_t vendor_data[0]; // Vendor-specific data (if any)
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_reject_packet;
+/* NOP-Out may be used by an initiator as a "ping request" to verify
+ that a connection/session is still active and all its components are
+ operational. The NOP-In response is the "ping echo".
+
+ A NOP-Out is also sent by an initiator in response to a NOP-In.
+
+ A NOP-Out may also be used to confirm a changed ExpStatSN if another
+ PDU will not be available for a long time.
+
+ Upon receipt of a NOP-In with the Target Transfer Tag set to a valid
+ value (not the reserved value 0xffffffff), the initiator MUST respond
+ with a NOP-Out. In this case, the NOP-Out Target Transfer Tag MUST
+ contain a copy of the NOP-In Target Transfer Tag. The initiator
+
+ SHOULD NOT send a NOP-Out in response to any other received NOP-In,
+ in order to avoid lengthy sequences of NOP-In and NOP-Out PDUs sent
+ in response to each other.
+*/
+typedef struct __attribute__((packed)) iscsi_nop_out {
+ uint8_t opcode; // Always 0x00 according to specification (see above)
+ uint8_t reserved[3]; // Reserved for future usage
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ uint64_t lun; // LUN or Reserved
+ uint32_t init_task_tag; // The NOP-Out MUST have the Initiator Task Tag set to a valid value
+ // only if a response in the form of a NOP-In is requested (i.e., the
+ // NOP-Out is used as a ping request). Otherwise, the Initiator Task
+ // Tag MUST be set to 0xFFFFFFFF.
+ // When a target receives the NOP-Out with a valid Initiator Task Tag,
+ // it MUST respond with a NOP-In Response.
+ // If the Initiator Task Tag contains 0xFFFFFFFF, the I bit MUST be set
+ // to 1, and the CmdSN is not advanced after this PDU is sent
+ uint32_t target_xfer_tag; // The Target Transfer Tag is a target-assigned identifier for the
+ // operation.
+ // The NOP-Out MUST only have the Target Transfer Tag set if it is
+ // issued in response to a NOP-In with a valid Target Transfer Tag. In
+ // this case, it copies the Target Transfer Tag from the NOP-In PDU.
+ // Otherwise, the Target Transfer Tag MUST be set to 0xFFFFFFFF.
+ // When the Target Transfer Tag is set to a value other than 0xFFFFFFFF,
+ // the LUN field MUST also be copied from the NOP-In
+ uint32_t cmd_sn; // CmdSN
+ uint32_t exp_stat_sn; // ExpStatSN
+ uint64_t reserved2[2]; // Reserved for future usage
+ struct iscsi_header_digest hdr_digest; // Optional header digest
+ struct iscsi_ds_cmd_data ds_ping_data; // DataSegment - Ping Data (optional)
+ // Ping data is reflected in the NOP-In Response. The length of the
+ // reflected data is limited to MaxRecvDataSegmentLength. The length of
+ // ping data is indicated by the DataSegmentLength. 0 is a valid value
+ // for the DataSegmentLength and indicates the absence of ping data
+ struct iscsi_data_digest data_digest; // Optional data digest
+} iscsi_nop_out;
+
+/* NOP-In is sent by a target as either a response to a NOP-Out, a
+ "ping" to an initiator, or a means to carry a changed ExpCmdSN and/or
+ MaxCmdSN if another PDU will not be available for a long time (as
+ determined by the target).
+
+ When a target receives the NOP-Out with a valid Initiator Task Tag
+ (not the reserved value 0xFFFFFFFF), it MUST respond with a NOP-In
+ with the same Initiator Task Tag that was provided in the NOP-Out
+ request. It MUST also duplicate up to the first
+ MaxRecvDataSegmentLength bytes of the initiator-provided Ping Data.
+ For such a response, the Target Transfer Tag MUST be 0xFFFFFFFF. The
+
+ target SHOULD NOT send a NOP-In in response to any other received
+ NOP-Out in order to avoid lengthy sequences of NOP-In and NOP-Out
+ PDUs sent in response to each other.
+
+ Otherwise, when a target sends a NOP-In that is not a response to a
+ NOP-Out received from the initiator, the Initiator Task Tag MUST be
+ set to 0xFFFFFFFF, and the data segment MUST NOT contain any data
+ (DataSegmentLength MUST be 0).
+*/
+
+typedef struct __attribute__((packed)) iscsi_nop_in {
+ uint8_t opcode; // Always 0x20 according to specification (see above)
+ uint8_t reserved[3]; // Reserved for future usage
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ uint64_t lun; // A LUN MUST be set to a correct value when the Target Transfer Tag is
+ // valid (not the reserved value 0xFFFFFFFF)
+ uint32_t init_task_tag; // Initiator task tag or 0xFFFFFFFF
+ uint32_t target_xfer_tag; // If the target is responding to a NOP-Out, this field is set to the
+ // reserved value 0xFFFFFFFF.
+ // If the target is sending a NOP-In as a ping (intending to receive a
+ // corresponding NOP-Out), this field is set to a valid value (not the
+ // reserved value 0xFFFFFFFF).
+ // If the target is initiating a NOP-In without wanting to receive a
+ // corresponding NOP-Out, this field MUST hold the reserved value
+ // 0xFFFFFFFF
+ uint32_t stat_sn; // The StatSN field will always contain the next StatSN. However, when
+ // the Initiator Task Tag is set to 0xFFFFFFFF, the StatSN for the
+ // connection is not advanced after this PDU is sent
+ uint32_t exp_cmd_sn; // ExpCmdSN
+ uint32_t max_cmd_sn; // MaxCmdSN
+ uint32_t reserved[3]; // Reserved for future usage
+ struct iscsi_header_digest hdr_digest; // Optional header digest
+ struct iscsi_ds_cmd_data ds_ping_data; // DataSegment - Return Ping Data
+ struct iscsi_data_digest data_digest; // Optional data digest
+} iscsi_nop_in;
#endif /* DNBD3_ISCSI_H_ */