summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Vater2025-07-08 16:37:35 +0200
committerSebastian Vater2025-07-08 16:37:35 +0200
commit711f54498a2deb7a28f8a1f52af8fea4831e9b7d (patch)
treed5c89f7407aa08b088dab4a03008059984b4d04d
parentAdded iSCSI async message packet to iscsi header file. (diff)
downloaddnbd3-711f54498a2deb7a28f8a1f52af8fea4831e9b7d.tar.gz
dnbd3-711f54498a2deb7a28f8a1f52af8fea4831e9b7d.tar.xz
dnbd3-711f54498a2deb7a28f8a1f52af8fea4831e9b7d.zip
Removed accidental else if clause in server/net.c causing compile failure. Also Added login and other stuff to iscsi.h.
-rw-r--r--src/server/iscsi.h513
-rw-r--r--src/server/net.c2
2 files changed, 491 insertions, 24 deletions
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index b94f9ec..5241728 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -512,7 +512,7 @@ typedef struct __attribute__((packed)) iscsi_task_mgmt_func_response_packet {
// c) if the Referenced Task Tag does not identify an existing task
// and the CmdSN indicated by the RefCmdSN field in the Task
// Management Function Request is outside the valid CmdSN window,
- // then targets must return the "Task does not exist" response.
+ // then targets must return the "Task does not exist" response
uint8_t reserved2; // Reserved for future usage
uint8_t total_ahs_len; // TotalAHSLength (MUST be 0 for this PDU)
uint8_t ds_len[3]; // DataSegmentLength (MUST be 0 for this PDU)
@@ -520,7 +520,7 @@ typedef struct __attribute__((packed)) iscsi_task_mgmt_func_response_packet {
uint32_t init_task_tag; // Initiator task tag
uint32_t reserved4; // Reserved for future usage
uint32_t stat_sn; // StatSN
- uint32_t exp_cmnd_sn; // ExpCmdSN
+ uint32_t exp_cmd_sn; // ExpCmdSN
uint32_t max_cmd_sn; // MaxCmdSN
uint32_t reserved5[3]; // Reserved for future usage
struct iscsi_header_digest hdr_digest; // Optional header digest
@@ -626,7 +626,7 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
// status (and of a residual count) is signaled via the S flag bit.
// Although targets MAY choose to send even non-exception status in
// separate responses, initiators MUST support non-exception status in
- // Data-In PDUs.
+ // Data-In PDUs
uint8_t total_ahs_len; // TotalAHSLength
uint8_t ds_len[3]; // DataSegmentLength
// This is the data payload length of a SCSI Data-In or SCSI Data-Out
@@ -635,11 +635,11 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
// segments.
// The data segments of Data-In and Data-Out PDUs SHOULD be filled to
// the integer number of 4-byte words (real payload), unless the F bit
- // is set to 1.
- uint64_t lun; // Logical Unit Number (LUN) or Reserved.
+ // is set to 1
+ uint64_t lun; // Logical Unit Number (LUN) or Reserved
// If the Target Transfer Tag isprovided, then the LUN field MUST hold a
// valid value and be consistent with whatever was specified with the command;
- // otherwise, the LUN field is reserved.
+ // otherwise, the LUN field is reserved
uint32_t init_task_tag; // Initiator task tag
uint32_t target_xfer_tag; // On outgoing data, the Target Transfer Tag is provided to the target
// if the transfer is honoring an R2T. In this case, the Target
@@ -652,9 +652,9 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
// Data-In PDU with the A bit set to 1.
// The Target Transfer Tag values are not specified by this protocol,
// except that the value 0xFFFFFFFF is reserved and means that the
- // Target Transfer Tag is not supplied.
+ // Target Transfer Tag is not supplied
uint32_t stat_sn; // StatSN
- uint32_t exp_cmnd_sn; // ExpCmdSN
+ uint32_t exp_cmd_sn; // ExpCmdSN
uint32_t max_cmd_sn; // MaxCmdSN
uint32_t data_sn; // DataSN
// For input (read) or bidirectional Data-In PDUs, the DataSN is the
@@ -666,7 +666,7 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
// within the current output sequence. Either the current output
// sequence is identified by the Initiator Task Tag (for unsolicited
// data) or it is a data sequence generated for one R2T (for data
- // solicited through R2T).
+ // solicited through R2T)
uint32_t buf_offset; // Buffer Offset
// The Buffer Offset field contains the offset of this PDU payload data
// within the complete data transfer. The sum of the buffer offset and
@@ -677,7 +677,7 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
// increasing buffer offset order and overlays are forbidden.
// The ordering between sequences is determined by DataSequenceInOrder.
// When set to Yes, it means that sequences have to be in increasing
- // buffer offset order and overlays are forbidden.
+ // buffer offset order and overlays are forbidden
uint32_t res_cnt; // Residual Count or Reserved
struct iscsi_header_digest hdr_digest; // Optional header digest
struct iscsi_ds_cmd_data ds_cmd_data; // Data segment
@@ -741,12 +741,12 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
uint8_t reserved[3]; // Reserved for future usage
uint8_t total_ahs_len; // TotalAHSLength, MUST be 0 for this PDU
uint8_t ds_len[3]; // DataSegmentLength, MUST be 0 0 for this PDU
- uint64_t lun; // Logical Unit Number (LUN) or Reserved.
+ uint64_t lun; // Logical Unit Number (LUN) or Reserved
uint32_t init_task_tag; // Initiator task tag
uint32_t target_xfer_tag; // Target transfer tag
uint32_t stat_sn; // The StatSN field will contain the next StatSN. The StatSN for this
- // connection is not advanced after this PDU is sent.
- uint32_t exp_cmnd_sn; // ExpCmdSN
+ // connection is not advanced after this PDU is sent
+ uint32_t exp_cmd_sn; // ExpCmdSN
uint32_t max_cmd_sn; // MaxCmdSN
uint32_t data_sn; // DataSN
uint32_t r2t_sn; // R2TSN is the R2T PDU input PDU number within the command identified
@@ -756,13 +756,13 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
uint32_t buf_offset; // Buffer Offset
// The target therefore also specifies a buffer offset that
// indicates the point at which the data transfer should begin, relative
- // to the beginning of the total data transfer.
+ // to the beginning of the total data transfer
uint32_t des_data_xfer_len; // Desired Data Transfer Length
// The target specifies how many bytes it wants the initiator to send
// because of this R2T PDU. The target may request the data from the
// initiator in several chunks, not necessarily in the original order of
// the data. The Desired Data Transfer Length MUST NOT be 0 and MUST NOT
- // exceed MaxBurstLength.
+ // exceed MaxBurstLength
struct iscsi_header_digest hdr_digest; // Optional header digest
} iscsi_r2t_packet;
@@ -788,7 +788,7 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
// log out in Parameter3 seconds, the target should send an Async
// PDU with iSCSI event code "Dropped the connection" if possible
// or simply terminate the transport connection. Parameter1 and
- // Parameter2 are reserved.
+ // Parameter2 are reserved
#define ISCSI_ASYNC_MSG_EVENT_CONNECT_DROP_NOTIFY 0x02 // (Connection Drop Notification) - the target indicates that it
// will drop the connection.
// The Parameter1 field indicates the CID of the connection that
@@ -806,7 +806,7 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
// other responses should be expected from the target for the
// outstanding commands on this connection.
// A value of 0 for Parameter2 indicates that reconnect can be
- // attempted immediately.
+ // attempted immediately
#define ISCSI_ASYNC_MSG_EVENT_SESSION_DROP_NOTIFY 0x03 // (Session Drop Notification) - the target indicates that it
// will drop all the connections of this session.
// The Parameter1 field is reserved.
@@ -822,7 +822,7 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
// commands in this session; no other responses should be
// expected from the target for the outstanding commands in this
// session. A value of 0 for Parameter2 indicates that reconnect
- // can be attempted immediately.
+ // can be attempted immediately
#define ISCSI_ASYNC_MSG_EVENT_NEGOTIATION_REQUEST 0x04 // (Negotiation Request) - the target requests parameter
// negotiation on this connection. The initiator MUST honor this
// request by issuing a Text Request (that can be empty) on the
@@ -831,7 +831,7 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
// on the connection, or by issuing a Logout Request. If the
// initiator does not issue a Text Request, the target may
// reissue the Asynchronous Message requesting parameter
- // negotiation.
+ // negotiation
#define ISCSI_ASYNC_MSG_EVENT_TASK_TERMINATION 0x05 // (Task Termination) - all active tasks for a LU with a matching
// LUN field in the Async Message PDU are being terminated. The
// receiving initiator iSCSI layer MUST respond to this message
@@ -844,7 +844,7 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
// NOP-Out.
// This value of AsyncEvent, however, MUST NOT be used on an
// iSCSI session unless the new TaskReporting text key was
- // negotiated to FastAbort on the session.
+ // negotiated to FastAbort on the session
#define ISCSI_ASYNC_MSG_EVENT_VENDOR_FIRST 0xF8 // First vendor-specific iSCSI event. The AsyncVCode details the
// vendor code, and data MAY accompany the report
#define ISCSI_ASYNC_MSG_EVENT_VENDOR_LAST 0xFF // Last vendor-specific iSCSI event. The AsyncVCode details the
@@ -862,18 +862,18 @@ typedef struct __attribute__((packed)) iscsi_async_msg_packet {
uint8_t total_ahs_len; // TotalAHSLength, MUST be 0 for this PDU
uint8_t ds_len[3]; // DataSegmentLength, MUST be 0 0 for this PDU
uint64_t lun; // The LUN field MUST be valid if AsyncEvent is 0. Otherwise, this
- // field is reserved.
+ // field is reserved
uint32_t tag; // Tag (always 0xFFFFFFFF for now)
uint32_t reserved2; // Reserved for future usage
uint32_t stat_sn; // StatSN
// The StatSN counts this PDU as an acknowledgeable event (the StatSN is
// advanced), which allows for initiator and target state synchronization.
- uint32_t exp_cmnd_sn; // ExpCmdSN
+ uint32_t exp_cmd_sn; // ExpCmdSN
uint32_t max_cmd_sn; // MaxCmdSN
uint8_t async_event; // AsyncEvent
uint8_t async_vcode; // AsyncVCode is a vendor-specific detail code that is only valid if the
// AsyncEvent field indicates a vendor-specific event. Otherwise, it is
- // reserved.
+ // reserved
uint16_t param_1; // Parameter1 or Reserved
uint16_t param_2; // Parameter2 or Reserved
uint16_t param_3; // Parameter3 or Reserved
@@ -883,4 +883,471 @@ typedef struct __attribute__((packed)) iscsi_async_msg_packet {
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_async_msg_packet;
+/* For a SCSI event, this data accompanies the report in the data
+ segment and identifies the condition.
+
+ For an iSCSI event, additional vendor-unique data MAY accompany the
+ Async event. Initiators MAY ignore the data when not understood,
+ while processing the rest of the PDU.
+
+ If the DataSegmentLength is not 0, the format of the DataSegment is
+ as follows:
+*/
+typedef struct __attribute__((packed)) iscsi_sense_event_data_packet {
+ uint16_t sense_len; // SenseLength
+ // This is the length of Sense Data. When the Sense Data field is empty
+ // (e.g., the event is not a SCSI event), SenseLength is 0
+ uint16_t sense_data[0]; // Sense Data
+ uint16_t event_data[0]; // iSCSI Event Data
+} iscsi_sense_event_data_packet;
+
+#define ISCSI_TEXT_REQ_FLAGS_CONTINUE (1 << 6) // (C) When set to 1, this bit indicates that the text (set of key=value
+ // pairs) in this Text Request is not complete (it will be continued on
+ // subsequent Text Requests); otherwise, it indicates that this Text
+ // Request ends a set of key=value pairs. A Text Request with the C bit
+ // set to 1 MUST have the F bit set to 0.
+#define ISCSI_TEXT_REQ_FLAGS_FINAL (1 << 7) // (F) When set to 1, this bit indicates that this is the last or only Text
+ // Request in a sequence of Text Requests; otherwise, it indicates that
+ // more Text Requests will follow.
+
+/* The Text Request is provided to allow for the exchange of information
+ and for future extensions. It permits the initiator to inform a
+ target of its capabilities or request some special operations.
+
+ An initiator MUST NOT have more than one outstanding Text Request on
+ a connection at any given time.
+
+ On a connection failure, an initiator must either explicitly abort
+ any active allegiant text negotiation task or cause such a task to be
+ implicitly terminated by the target.
+*/
+typedef struct __attribute__((packed)) iscsi_text_req_packet {
+ uint8_t opcode; // Always 0x04 according to specification (see above)
+ int8_t flags; // Text request flags (see above)
+ uint8_t reserved[2]; // Reserved for future usage
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ uint64_t lun; // Logical Unit Number (LUN) or Reserved
+ uint32_t init_task_tag; // This is the initiator-assigned identifier for this Text Request. If
+ // the command is sent as part of a sequence of Text Requests and
+ // responses, the Initiator Task Tag MUST be the same for all the
+ // requests within the sequence (similar to linked SCSI commands). The
+ // I bit for all requests in a sequence also MUST be the same
+ uint32_t target_xfer_tag; // When the Target Transfer Tag is set to the reserved value 0xFFFFFFFF,
+ // it tells the target that this is a new request, and the target resets
+ // any internal state associated with the Initiator Task Tag (resets the
+ // current negotiation state).
+ // The target sets the Target Transfer Tag in a Text Response to a value
+ // other than the reserved value 0xFFFFFFFF whenever it indicates that
+ // it has more data to send or more operations to perform that are
+ // associated with the specified Initiator Task Tag. It MUST do so
+ // whenever it sets the F bit to 0 in the response. By copying the
+ // Target Transfer Tag from the response to the next Text Request, the
+ // initiator tells the target to continue the operation for the specific
+ // Initiator Task Tag. The initiator MUST ignore the Target Transfer
+ // Tag in the Text Response when the F bit is set to 1.
+ // This mechanism allows the initiator and target to transfer a large
+ // amount of textual data over a sequence of text-command/text-response
+ // exchanges or to perform extended negotiation sequences.
+ // If the Target Transfer Tag is not 0xFFFFFFFF, the LUN field MUST be
+ // sent by the target in the Text Response.
+ // A target MAY reset its internal negotiation state if an exchange is
+ // stalled by the initiator for a long time or if it is running out of
+ // resources.
+ // Long Text Responses are handled as shown in the following example:
+ // I->T Text SendTargets=All (F = 1, TTT = 0xFFFFFFFF)
+ // T->I Text <part 1> (F = 0, TTT = 0x12345678)
+ // I->T Text <empty> (F = 1, TTT = 0x12345678)
+ // T->I Text <part 2> (F = 0, TTT = 0x12345678)
+ // I->T Text <empty> (F = 1, TTT = 0x12345678)
+ // ...
+ // T->I Text <part n> (F = 1, TTT = 0xFFFFFFFF)
+ 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_cmd_data; // Data segment
+ // The data lengths of a Text Request MUST NOT exceed the iSCSI target
+ // MaxRecvDataSegmentLength (a parameter that is negotiated per
+ // connection and per direction).
+ // A key=value pair can span Text Request or Text Response boundaries.
+ // A key=value pair can start in one PDU and continue on the next. In
+ // other words, the end of a PDU does not necessarily signal the end of
+ // a key=value pair.
+ // The target responds by sending its response back to the initiator.
+ // The response text format is similar to the request text format. The
+ // Text Response MAY refer to key=value pairs presented in an earlier
+ // Text Request, and the text in the request may refer to earlier
+ // responses.
+ // Text operations are usually meant for parameter setting/negotiations
+ // but can also be used to perform some long-lasting operations
+ struct iscsi_data_digest data_digest; // Optional data digest
+} iscsi_text_req_packet;
+
+#define ISCSI_TEXT_RESPONSE_FLAGS_CONTINUE (1 << 6) // (C) When set to 1, this bit indicates that the text (set of key=value
+ // pairs) in this Text Response is not complete (it will be continued on
+ // subsequent Text Responses); otherwise, it indicates that this Text
+ // Response ends a set of key=value pairs. A Text Response with the
+ // C bit set to 1 MUST have the F bit set to 0
+#define ISCSI_TEXT_RESPONSE_FLAGS_FINAL (1 << 7) // (F) When set to 1, in response to a Text Request with the Final bit set
+ // to 1, the F bit indicates that the target has finished the whole
+ // operation. Otherwise, if set to 0 in response to a Text Request with
+ // the Final Bit set to 1, it indicates that the target has more work to
+ // do (invites a follow-on Text Request). A Text Response with the
+ // F bit set to 1 in response to a Text Request with the F bit set to 0
+ // is a protocol error.
+ // A Text Response with the F bit set to 1 MUST NOT contain key=value
+ // pairs that may require additional answers from the initiator.
+ // A Text Response with the F bit set to 1 MUST have a Target Transfer
+ // Tag field set to the reserved value 0xFFFFFFFF.
+ // A Text Response with the F bit set to 0 MUST have a Target Transfer
+ // Tag field set to a value other than the reserved value 0xFFFFFFFF
+
+/* The Text Response PDU contains the target's responses to the
+ initiator's Text Request. The format of the Text field matches that
+ of the Text Request.
+*/
+typedef struct __attribute__((packed)) iscsi_text_response_packet {
+ uint8_t opcode; // Always 0x24 according to specification (see above)
+ int8_t flags; // Text response flags (see above)
+ uint8_t reserved[2]; // Reserved for future usage
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ uint64_t lun; // Logical Unit Number (LUN) or Reserved
+ uint32_t init_task_tag; // The Initiator Task Tag matches the tag used in the initial Text Request
+ uint32_t target_xfer_tag; // When a target has more work to do (e.g., cannot transfer all the
+ // remaining text data in a single Text Response or has to continue the
+ // negotiation) and has enough resources to proceed, it MUST set the
+ // Target Transfer Tag to a value other than the reserved value
+ // 0xFFFFFFFF. Otherwise, the Target Transfer Tag MUST be set to
+ // 0xFFFFFFFF.
+ // When the Target Transfer Tag is not 0xFFFFFFFF, the LUN field may be
+ // significant.
+ // The initiator MUST copy the Target Transfer Tag and LUN in its next
+ // request to indicate that it wants the rest of the data.
+ // When the target receives a Text Request with the Target Transfer Tag
+ // set to the reserved value 0xFFFFFFFF, it resets its internal
+ // information (resets state) associated with the given Initiator Task
+ // Tag (restarts the negotiation).
+ // When a target cannot finish the operation in a single Text Response
+ // and does not have enough resources to continue, it rejects the Text
+ // Request with the appropriate Reject code.
+ // A target may reset its internal state associated with an Initiator
+ // Task Tag (the current negotiation state) as expressed through the
+ // Target Transfer Tag if the initiator fails to continue the exchange
+ // for some time. The target may reject subsequent Text Requests with
+ // the Target Transfer Tag set to the "stale" value
+ uint32_t stat_sn; // StatSN. The target StatSN variable is advanced by each Text Response sent
+ uint32_t exp_cmd_sn; // ExpCmdSN
+ uint32_t max_cmd_sn; // MaxCmdSN
+ uint64_t reserved2[2]; // Reserved for future usage
+ struct iscsi_header_digest hdr_digest; // Optional header digest
+ struct iscsi_ds_cmd_data ds_cmd_data; // Data segment
+ // The data lengths of a Text Response MUST NOT exceed the iSCSI
+ // initiator MaxRecvDataSegmentLength (a parameter that is negotiated
+ // per connection and per direction).
+ // The text in the Text Response Data is governed by the same rules as
+ // the text in the Text Request Data.
+ // Although the initiator is the requesting party and controls the
+ // request-response initiation and termination, the target can offer
+ // key=value pairs of its own as part of a sequence and not only in
+ // response to the initiator
+ struct iscsi_data_digest data_digest; // Optional data digest
+} iscsi_text_response_packet;
+
+#define ISCSI_ISID_TYPE_BITS (1 << 6) // Two bits - The T field identifies the format and usage of A, B, C, and D as
+ // indicated below:
+#define ISCSI_ISID_TYPE_FORMAT_OUI 0x0 // OUI-Format
+ // A and B: 22-bit OUI
+ // (the I/G and U/L bits are omitted)
+ // C and D: 24-bit Qualifier
+#define ISCSI_ISID_TYPE_FORMAT_EN 0x1 // EN: Format (IANA Enterprise Number)
+ // A: Reserved
+ // B and C: EN (IANA Enterprise Number)
+ // D: Qualifier
+#define ISCSI_ISID_TYPE_FORMAT_RANDOM 0x2 // Random
+ // A: Reserved
+ // B and C: Random
+ // D: Qualifier
+
+/* This is an initiator-defined component of the session identifier and
+ is structured as follows:
+
+ For the T field values 00b and 01b, a combination of A and B (for
+ 00b) or B and C (for 01b) identifies the vendor or organization whose
+ component (software or hardware) generates this ISID. A vendor or
+ organization with one or more OUIs, or one or more Enterprise
+ Numbers, MUST use at least one of these numbers and select the
+ appropriate value for the T field when its components generate ISIDs.
+ An OUI or EN MUST be set in the corresponding fields in network byte
+ order (byte big-endian).
+
+ If the T field is 10b, B and C are set to a random 24-bit unsigned
+ integer value in network byte order (byte big-endian).
+
+ The Qualifier field is a 16-bit or 24-bit unsigned integer value that
+ provides a range of possible values for the ISID within the selected
+ namespace. It may be set to any value within the constraints
+ specified in the iSCSI protocol.
+
+ If the ISID is derived from something assigned to a hardware adapter
+ or interface by a vendor as a preset default value, it MUST be
+ configurable to a value assigned according to the SCSI port behavior
+ desired by the system in which it is installed. The resultant ISID
+ MUST also be persistent over power cycles, reboot, card swap, etc.
+*/
+typedef struct __attribute__((packed)) iscsi_isid {
+ uint8_t a; // Meaning depends on T bit (see above)
+ uint16_t b; // Meaning depends on T bit (see above)
+ uint8_t c; // Meaning depends on T bit (see above)
+ uint16_t d; // Meaning depends on T bit (see above)
+}
+
+#define ISCSI_LOGIN_REQ_FLAGS_NEXT_STAGE_SECURITY_NEGOTIATION 0x0 // SecurityNegotiation
+#define ISCSI_LOGIN_REQ_FLAGS_NEXT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 0x1 // LoginOperationalNegotiation
+#define ISCSI_LOGIN_REQ_FLAGS_NEXT_STAGE_FULL_FEATURE_PHASE 0x3 // FullFeaturePhase
+#define ISCSI_LOGIN_REQ_FLAGS_NEXT_STAGE (1 << 0) // (NSG) - Two bits - the Login negotiation requests and responses are
+ // associated with a specific stage in the session (SecurityNegotiation,
+ // LoginOperationalNegotiation, FullFeaturePhase) and may indicate the
+ // next stage to which they want to move. The Next Stage value is only
+ // valid when the T bit is 1; otherwise, it is reserved
+#define ISCSI_LOGIN_REQS_FLAGS_GET_NEXT_STAGE(x) ((x) & 3)
+
+#define ISCSI_LOGIN_REQ_FLAGS_CURRENT_STAGE_SECURITY_NEGOTIATION 0x0 // SecurityNegotiation
+#define ISCSI_LOGIN_REQ_FLAGS_CURRENT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 0x1 // LoginOperationalNegotiation
+#define ISCSI_LOGIN_REQ_FLAGS_CURRENT_STAGE_FULL_FEATURE_PHASE 0x3 // FullFeaturePhase
+#define ISCSI_LOGIN_REQ_FLAGS_CURRENT_STAGE (1 << 2) // (CSG) - Two bits - the Login negotiation requests and responses are
+ // associated with aspecific stage in the session (SecurityNegotiation,
+ // LoginOperationalNegotiation, FullFeaturePhase) and may indicate the
+ // next stage to which they want to move
+#define ISCSI_LOGIN_REQS_FLAGS_GET_CURRENT_STAGE(x) (((x) >> 2) & 3)
+
+#define ISCSI_LOGIN_REQ_FLAGS_CONTINUE (1 << 6) // (C) When set to 1, this bit indicates that the text (set of key=value
+ // pairs) in this Login Request is not complete (it will be continued on
+ // subsequent Login Requests); otherwise, it indicates that this Login
+ // Request ends a set of key=value pairs. A Login Request with the
+ // C bit set to 1 MUST have the T bit set to 0.
+#define ISCSI_LOGIN_REQ_FLAGS_TRANSMIT (1 << 7) // (T) When set to 1, this bit indicates that the initiator is ready to
+ // transit to the next stage.
+ // If the T bit is set to 1 and the NSG is set to FullFeaturePhase, then
+ // this also indicates that the initiator is ready for the Login
+ // Final-Response.
+
+/* After establishing a TCP connection between an initiator and a
+ target, the initiator MUST start a Login Phase to gain further access
+ to the target's resources.
+
+ The Login Phase consists of a sequence of Login Requests and Login
+ Responses that carry the same Initiator Task Tag.
+
+ Login Requests are always considered as immediate.
+*/
+typedef struct __attribute__((packed)) iscsi_login_req_packet {
+ uint8_t opcode; // Always 0x03 according to specification (see above)
+ int8_t flags; // Login request flags (see above)
+ uint8_t version_max; // Version-max indicates the maximum version number supported.
+ // All Login Requests within the Login Phase MUST carry the same
+ // Version-max. Currently, this is always 0
+ // The target MUST use the value presented with the first Login Request.
+ uint8_t version_min; // All Login Requests within the Login Phase MUST carry the same
+ // Version-min. The target MUST use the value presented with the first
+ // Login Request. Always 0 for now
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ struct iscsi_isid isid; // ISID (see above for declaration)
+ uint16_t tsih; // The TSIH must be set in the first Login Request. The reserved value
+ // 0 MUST be used on the first connection for a new session. Otherwise,
+ // the TSIH sent by the target at the conclusion of the successful login
+ // of the first connection for this session MUST be used. The TSIH
+ // identifies to the target the associated existing session for this new
+ // connection.
+ // All Login Requests within a Login Phase MUST carry the same TSIH.
+ // The target MUST check the value presented with the first Login
+ // Request
+ uint32_t init_task_tag; // Initiator task tag
+ uint16_t cid; // Connection ID. The CID provides a unique ID for this connection within the session.
+ // All Login Requests within the Login Phase MUST carry the same CID.
+ // The target MUST use the value presented with the first Login Request.
+ // A Login Request with a non-zero TSIH and a CID equal to that of an
+ // existing connection implies a logout of the connection followed by a
+ // login
+ uint32_t cmd_sn; // The CmdSN is either the initial command sequence number of a session
+ // (for the first Login Request of a session - the "leading" login) or
+ // the command sequence number in the command stream if the login is for
+ // a new connection in an existing session.
+ // Examples:
+ // - Login on a leading connection: If the leading login carries the
+ // CmdSN 123, all other Login Requests in the same Login Phase carry
+ // the CmdSN 123, and the first non-immediate command in the Full
+ // Feature Phase also carries the CmdSN 123.
+ // - Login on other than a leading connection: If the current CmdSN at
+ // the time the first login on the connection is issued is 500, then
+ // that PDU carries CmdSN=500. Subsequent Login Requests that are
+ // needed to complete this Login Phase may carry a CmdSN higher than
+ // 500 if non-immediate requests that were issued on other connections
+ // in the same session advance the CmdSN.
+ // If the Login Request is a leading Login Request, the target MUST use
+ // the value presented in the CmdSN as the target value for the
+ // ExpCmdSN
+ uint32_t exp_stat_sn; // For the first Login Request on a connection, this is the ExpStatSN
+ // for the old connection, and this field is only valid if the Login
+ // Request restarts a connection
+ // For subsequent Login Requests, it is used to acknowledge the Login
+ // Responses with their increasing StatSN values
+ uint64_t reserved[2]; // Reserved for future usage
+ struct iscsi_ds_cmd_data ds_cmd_data; // Data segment - Login Parameters in Text Request Format
+ // The initiator MUST provide some basic parameters in order
+ // to enable the target to determine if the initiator may use
+ // the target's resources and the initial text parameters for the security exchange.
+} iscsi_login_req_packet;
+
+#define ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_SECURITY_NEGOTIATION 0x0 // SecurityNegotiation
+#define ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 0x1 // LoginOperationalNegotiation
+#define ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_FULL_FEATURE_PHASE 0x3 // FullFeaturePhase
+#define ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE (1 << 0) // (NSG) - Two bits - the Login negotiation requests and responses are
+ // associated with a specific stage in the session (SecurityNegotiation,
+ // LoginOperationalNegotiation, FullFeaturePhase) and may indicate the
+ // next stage to which they want to move The Next Stage value is only
+ // valid when the T bit is 1; otherwise, it is reserved
+#define ISCSI_LOGIN_RESPONSE_FLAGS_GET_NEXT_STAGE(x) ((x) & 3)
+
+#define ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_SECURITY_NEGOTIATION 0x0 // SecurityNegotiation
+#define ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 0x1 // LoginOperationalNegotiation
+#define ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_FULL_FEATURE_PHASE 0x3 // FullFeaturePhase
+#define ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE (1 << 2) // (CSG) - Two bits - the Login negotiation requests and responses are
+ // associated with aspecific stage in the session (SecurityNegotiation,
+ // LoginOperationalNegotiation, FullFeaturePhase) and may indicate the
+ // next stage to which they want to move
+#define ISCSI_LOGIN_RESPONSE_FLAGS_GET_CURRENT_STAGE(x) (((x) >> 2) & 3)
+
+#define ISCSI_LOGIN_RESPONSE_FLAGS_CONTINUE (1 << 6) // (C) When set to 1, this bit indicates that the text (set of key=value
+ // pairs) in this Login Response is not complete (it will be continued
+ // on subsequent Login Responses); otherwise, it indicates that this
+ // Login Response ends a set of key=value pairs. A Login Response with
+ // the C bit set to 1 MUST have the T bit set to 0
+#define ISCSI_LOGIN_RESPONSE_FLAGS_TRANSMIT (1 << 7) // (T) The T bit is set to 1 as an indicator of the end of the stage. If
+ // the T bit is set to 1 and the NSG is set to FullFeaturePhase, then
+ // this is also the Login Final-Response. A T bit of 0 indicates a
+ // "partial" response, which means "more negotiation needed".
+ // A Login Response with the T bit set to 1 MUST NOT contain key=value
+ // pairs that may require additional answers from the initiator within
+ // the same stage.
+ // If the Status-Class is 0, the T bit MUST NOT be set to 1 if the T bit
+ // in the request was set to 0
+
+#define ISCSI_LOGIN_RESPONSE_STATUS_CLASS_SUCCESS 0x00 // Success - indicates that the iSCSI target successfully
+ // received, understood, and accepted the request. The numbering
+ // fields (StatSN, ExpCmdSN, MaxCmdSN) are only valid if Status-
+ // Class is 0
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SUCCESS 0x00 // Login is proceeding OK. If the response T bit is set to 1 in both the
+ // request and the matching response, and the NSG is set to
+ // FullFeaturePhase in both the request and the matching response, the
+ // Login Phase is finished, and the initiator may proceed to issue SCSI
+ // commands.
+
+#define ISCSI_LOGIN_RESPONSE_STATUS_CLASS_REDIRECT 0x01 // Redirection - indicates that the initiator must take further
+ // action to complete the request. This is usually due to the
+ // target moving to a different address. All of the redirection
+ // Status-Class responses MUST return one or more text key
+ // parameters of the type "TargetAddress", which indicates the
+ // target's new address. A redirection response MAY be issued by
+ // a target prior to or after completing a security negotiation if
+ // a security negotiation is required. A redirection SHOULD be
+ // accepted by an initiator, even without having the target
+ // complete a security negotiation if any security negotiation is
+ // required, and MUST be accepted by the initiator after the
+ // completion of the security negotiation if any security
+ // negotiation is required
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_REDIRECT_TEMP 0x01 // The requested iSCSI Target Name (ITN) has temporarily moved
+ // to the address provided
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_REDIRECT_PERM 0x02 // The requested ITN has permanently moved to the address provided
+
+#define ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR 0x02 // Initiator Error (not a format error) - indicates that the
+ // initiator most likely caused the error. This MAY be due to a
+ // request for a resource for which the initiator does not have
+ // permission. The request should not be tried again
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC 0x00 // Miscellaneous iSCSI initiator errors
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR 0x01 // The initiator could not be successfully
+ // authenticated or target authentication is
+ // not supported
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_FAIL 0x02 // The initiator is not allowed access to the
+ // given target
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_NOT_FOUND 0x03 // The requested ITN does not exist at this
+ // address
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_TARGET_REMOVED 0x04 // The requested ITN has been removed, and
+ // no forwarding address is provided
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_WRONG_VERSION 0x05 // The requested iSCSI version range is not
+ // supported by the target
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_TOO_MANY_CONNECTIONS 0x06 // Too many connections on this SSID
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISSING_PARAMETER 0x07 // Missing parameters (e.g. iSCSI Initiator
+ // Name and/or Target Name)
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_NO_SESSION_SPANNING 0x08 // arget does not support session spanning
+ // to this connection (address)
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_SESSION_NO_SUPPORT 0x09 // Target does not support this type of
+ // session or not from this initiator
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_SESSION_NO_EXIST 0x0A // Attempt to add a connection to a non-
+ // existent session
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_INVALID_LOGIN_REQ_TYPE 0x0B // Invalid request type during login
+
+#define ISCSI_LOGIN_RESPONSE_STATUS_CLASS_SERVER_ERR 0x03 // Target Error - indicates that the target sees no errors in the
+ // initiator's Login Request but is currently incapable of
+ // fulfilling the request. The initiator may retry the same Login
+ // Request later
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_TARGET_ERROR 0x00 // Target hardware or software error
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_SERVICE_UNAVAILABLE 0x01 // The iSCSI service or target is not
+ // currently operational
+#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_OUT_OF_RESOURCES 0x02 // The target has insufficient session,
+ // connection, or other resources
+
+/* The Login Response indicates the progress and/or end of the Login
+ Phase.
+*/
+typedef struct __attribute__((packed)) iscsi_login_response_packet {
+ uint8_t opcode; // Always 0x23 according to specification (see above)
+ int8_t flags; // Login response flags (see above)
+ uint8_t version_max; // This is the highest version number supported by the target.
+ // All Login Responses within the Login Phase MUST carry the same
+ // Version-max
+ uint8_t version_active; // Version-active indicates the highest version supported by the target
+ // and initiator. If the target does not support a version within the
+ // range specified by the initiator, the target rejects the login and
+ // this field indicates the lowest version supported by the target.
+ // All Login Responses within the Login Phase MUST carry the same
+ // Version-active.
+ // The initiator MUST use the value presented as a response to the first
+ // Login Request
+ uint8_t total_ahs_len; // TotalAHSLength
+ uint8_t ds_len[3]; // DataSegmentLength
+ struct iscsi_isid isid; // ISID (see above for declaration)
+ uint16_t tsih; // The TSIH is the target-assigned session-identifying handle. Its
+ // internal format and content are not defined by this protocol, except
+ // for the value 0, which is reserved. With the exception of the Login
+ // Final-Response in a new session, this field should be set to the TSIH
+ // provided by the initiator in the Login Request. For a new session,
+ // the target MUST generate a non-zero TSIH and ONLY return it in the
+ // Login Final-Response
+ uint32_t init_task_tag; // Initiator task tag
+ uint32_t reserved; // Reserved for future usage
+ uint32_t stat_sn; // For the first Login Response (the response to the first Login
+ // Request), this is the starting status sequence number for the
+ // connection. The next response of any kind - including the next
+ // Login Response, if any, in the same Login Phase - will carry this
+ // number + 1. This field is only valid if the Status-Class is 0
+ uint32_t exp_cmd_sn; // ExpCmdSN
+ uint32_t max_cmd_sn; // MaxCmdSN
+ uint8_t status_class; // Status-class (see above for details). If the Status-Class is
+ // not 0, the initiator and target MUST close the TCP connection
+ // If the target wishes to reject the Login Request for more than one
+ // reason, it should return the primary reason for the rejection
+ uint8_t status_detail; // Status-detail (see above for details)
+ uint16_t reserved2; // Reserved for future usage
+ uint64_t reserved3; // Reserved for future usage
+ struct iscsi_ds_cmd_data ds_cmd_data; // Data segment - Login Parameters in Text Request Format
+ // The target MUST provide some basic parameters in order to enable the
+ // initiator to determine if it is connected to the correct port and the
+ // initial text parameters for the security exchange.
+ // All the rules specified for Text Responses also hold for Login
+ // Responses.
+} iscsi_login_response_packet;
+
#endif /* DNBD3_ISCSI_H_ */
diff --git a/src/server/net.c b/src/server/net.c
index 3e5f3aa..629c491 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -181,7 +181,7 @@ void* net_handleNewConnection(void *clientPtr)
logadd( LOG_DEBUG1, "Magic in client handshake incorrect" );
}
goto fail_preadd;
- } else if (
+ }
// Magic OK, untangle byte order if required
fixup_request( request );
if ( request.cmd != CMD_SELECT_IMAGE ) {