summaryrefslogtreecommitdiffstats
path: root/src/server/iscsi.c
diff options
context:
space:
mode:
authorSimon Rettberg2025-10-14 19:15:20 +0200
committerSimon Rettberg2025-10-24 09:25:17 +0200
commit34818d50e7f7d3f31391ab31324939dcd381fbcd (patch)
treed33282aa1eae8e07b132ef5286bee635f5917243 /src/server/iscsi.c
parentWIP (diff)
downloaddnbd3-34818d50e7f7d3f31391ab31324939dcd381fbcd.tar.gz
dnbd3-34818d50e7f7d3f31391ab31324939dcd381fbcd.tar.xz
dnbd3-34818d50e7f7d3f31391ab31324939dcd381fbcd.zip
[SERVER] iscsi refactor: First working version
Diffstat (limited to 'src/server/iscsi.c')
-rw-r--r--src/server/iscsi.c1677
1 files changed, 381 insertions, 1296 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index cc08e29..2b39955 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -72,11 +72,6 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task);
static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task);
-
-
-
-
-
static void iscsi_scsi_task_create(iscsi_scsi_task *scsi_task); // Allocates and initializes a SCSI task
static void iscsi_scsi_task_xfer_complete(iscsi_scsi_task *scsi_task, iscsi_pdu *pdu); // Callback function when an iSCSI SCSI task completed the data transfer
@@ -89,15 +84,9 @@ static int iscsi_scsi_lun_get_from_iscsi(const uint64_t lun); // Converts an iSC
static void iscsi_scsi_lun_task_run( iscsi_scsi_task *scsi_task, iscsi_pdu *pdu); // Runs an iSCSI SCSI task for a specified iSCSI SCSI LUN
-static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size); // Reads a number of blocks from a block offset of a DNBD3 image to a specified buffer
-
+static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks); // Reads a number of blocks from a block offset of a DNBD3 image to a specified buffer
-
-static uint8_t *iscsi_vsprintf_append_realloc(char *buf, const char *format, va_list args); // Allocates and appends a buffer and sprintf's it
-static uint8_t *iscsi_sprintf_append_realloc(char *buf, const char *format, ...); // Allocates and appends a buffer and sprintf's it
-static uint8_t *iscsi_vsprintf_alloc(const char *format, va_list args); // Allocates a buffer and sprintf's it
-static uint8_t *iscsi_sprintf_alloc(const char *format, ... ); // Allocates a buffer and sprintf's it
static void iscsi_strcpy_pad(char *dst, const char *src, const size_t size, const int pad); // Copies a string with additional padding character to fill in a specified size
@@ -107,129 +96,25 @@ static void iscsi_task_destroy(iscsi_task *task); // Deallocates resources acqui
static void iscsi_task_response(iscsi_connection *conn, iscsi_task *task, iscsi_pdu *pdu); // Creates, initializes and sends an iSCSI task reponse PDU.
static uint64_t iscsi_target_node_wwn_get(const uint8_t *name); // Calculates the WWN using 64-bit IEEE Extended NAA for a name
-static dnbd3_image_t *iscsi_target_node_image_get(uint8_t *iqn); // Extracts the DNBD3 image out of an iSCSI IQN string and opens the DNBD3 image
static iscsi_session *iscsi_session_create(iscsi_connection *conn, const int type); // Creates and initializes an iSCSI session
static void iscsi_session_destroy(iscsi_session *session); // Deallocates all resources acquired by iscsi_session_create
-static iscsi_connection *iscsi_connection_create(dnbd3_client_t *sock); // Creates data structure for an iSCSI connection from iSCSI portal and TCP/IP socket
+static iscsi_connection *iscsi_connection_create(dnbd3_client_t *client); // Creates data structure for an iSCSI connection from iSCSI portal and TCP/IP socket
static void iscsi_connection_destroy(iscsi_connection *conn); // Deallocates all resources acquired by iscsi_connection_create
static int32_t iscsi_connection_read(const iscsi_connection *conn, uint8_t *buf, const uint32_t len); // Reads data for the specified iSCSI connection from its TCP socket
-static int32_t iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf, const uint32_t len); // Writes data for the specified iSCSI connection to its TCP socket
static void iscsi_connection_login_response_reject(iscsi_pdu *login_response_pdu, const iscsi_pdu *pdu); // Initializes a rejecting login response packet
-static iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn, const uint ahs_len, const int header_digest_size, const uint32_t ds_len, const int data_digest_size);
+static iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn, const uint32_t ds_len);
static void iscsi_connection_pdu_destroy(iscsi_pdu *pdu); // Destroys an iSCSI PDU structure used by connections
-static iscsi_bhs_packet *iscsi_connection_pdu_append(iscsi_pdu *pdu, const uint ahs_len, const int header_digest_size, const uint32_t ds_len, const int data_digest_size); // Appends packet data to an iSCSI PDU structure used by connections
-
-static void iscsi_connection_pdu_digest_header_update(iscsi_header_digest *header_digest, const iscsi_bhs_packet *packet_data, const uint ahs_len); // Calculate and store iSCSI header digest (CRC32C)
-static bool iscsi_connection_pdu_digest_header_verify(const iscsi_header_digest *header_digest, const iscsi_bhs_packet *packet_data, const uint ahs_len); // Validates a stored iSCSI header digest (CRC32C) with actual header data
-static void iscsi_connection_pdu_digest_data_update(iscsi_data_digest *data_digest, const iscsi_scsi_ds_cmd_data *ds_cmd_data, const uint32_t ds_len); // Calculate iSCSI data digest (CRC32C)
-static bool iscsi_connection_pdu_digest_data_verify(const iscsi_data_digest *data_digest, const iscsi_scsi_ds_cmd_data *ds_cmd_data, const uint32_t ds_len); // Validates a stored iSCSI data digest (CRC32C) with actual DataSegment
+static iscsi_bhs_packet *iscsi_connection_pdu_resize(iscsi_pdu *pdu, const uint ahs_len, const uint32_t ds_len); // Appends packet data to an iSCSI PDU structure used by connections
static bool iscsi_connection_pdu_write(iscsi_connection *conn, iscsi_pdu *pdu);
-
-/**
- * @brief Allocates and appends a buffer and sprintf's it.
- *
- * Merges multiple strings using printf style formatting
- * and allocates memory for holding the result.
- *
- * @param[in] buf Buffer to merge into.
- * @param[in] format printf style format string.
- * @param[in] args Values to fill in the format with.
- * @return New buffer which holds the final result.
- */
-static uint8_t *iscsi_vsprintf_append_realloc(char *buf, const char *format, va_list args)
-{
- va_list args_copy;
- uint orig_size = 0U;
-
- if ( buf != NULL )
- orig_size = (uint) strlen( (char *) buf );
-
- va_copy( args_copy, args );
- uint new_size = vsnprintf( NULL, 0, format, args_copy );
- va_end( args_copy );
-
- new_size += (uint) (orig_size + 1U);
-
- uint8_t *new_buf = realloc( buf, new_size );
-
- if ( new_buf == NULL ) {
- logadd( LOG_ERROR, "iscsi_vsprintf_append_realloc: Out of memory while allocating string buffer" );
-
- return NULL;
- }
-
- vsnprintf( (char *) (new_buf + orig_size), (new_size - orig_size), format, args );
-
- return new_buf;
-}
-
-/**
- * @brief Allocates and appends a buffer and sprintf's it.
- *
- * Merges strings using printf style formatting and allocates
- * memory for holding the result.
- *
- * @param[in] buf Buffer to merge into.
- * @param[in] format printf style format string.
- * @param[in] ... Values to fill in the format string with.
- * @return New buffer which holds the final result.
- */
-static uint8_t *iscsi_sprintf_append_realloc(char *buf, const char *format, ...)
-{
- va_list args;
-
- va_start( args, format );
- uint8_t *ret_buf = iscsi_vsprintf_append_realloc( buf, format, args );
- va_end( args );
-
- return ret_buf;
-}
-
-/**
- * @brief Allocates a buffer and sprintf's it.
- *
- * Merges strings using printf style formatting and allocates
- * memory for holding the result.
- *
- * @param[in] format printf style format string.
- * @param[in] args Values to fill in the format with.
- * @return New buffer which holds the final result.
- */
-static uint8_t *iscsi_vsprintf_alloc(const char *format, va_list args)
-{
- return iscsi_vsprintf_append_realloc( NULL, format, args );
-}
-
-/**
- * @brief Allocates a buffer and sprintf's it.
- *
- * Allocates a buffer large enough to hold printf style
- * string concatenation and fills it using vspnrintf.
- *
- * @param[in] format Format string to allocate and fill.
- * @param[in] ... Values to fill in the format string with.
- * @return New buffer containing the formatted string.
- */
-static uint8_t *iscsi_sprintf_alloc(const char *format, ... )
-{
- va_list args;
-
- va_start( args, format );
- uint8_t *buf = iscsi_vsprintf_alloc( format, args );
- va_end( args );
-
- return buf;
-}
-
/**
* @brief Copies a string with additional padding character to fill in a specified size.
*
@@ -263,7 +148,7 @@ static void iscsi_copy_kvp_int(const char *name, int *dest, const char *src)
const char *end = NULL;
if ( *dest != -1 ) {
- logadd( LOG_DEBUG1, "Received duplicate entry for key '%s', ignoring", name );
+ logadd( LOG_DEBUG1, "Received duplicate entry for key '%s', ignoring (new: %s, old: %d)", name, src, *dest );
return;
}
@@ -271,7 +156,7 @@ static void iscsi_copy_kvp_int(const char *name, int *dest, const char *src)
logadd( LOG_DEBUG1, "Empty value for numeric option '%s', ignoring", name );
return;
}
- res = strtoll( src, &end, 10 );
+ res = strtoll( src, (char **)&end, 10 ); // WTF why is the second arg not const char **
if ( end == NULL ) {
logadd( LOG_DEBUG1, "base 10 not valid! O.o" );
@@ -293,10 +178,10 @@ static void iscsi_copy_kvp_int(const char *name, int *dest, const char *src)
static void iscsi_copy_kvp_str(const char *name, const char **dest, const char *src)
{
if ( *dest != NULL ) {
- logadd( LOG_DEBUG1, "Received duplicate entry for key '%s', ignoring", name );
+ logadd( LOG_DEBUG1, "Received duplicate entry for key '%s', ignoring (new: %s, old: %s)", name, src, *dest );
return;
}
- *dest = strdup( src );
+ *dest = src;
}
/**
@@ -315,12 +200,12 @@ static void iscsi_copy_kvp_str(const char *name, const char **dest, const char *
* a negative value in case of an error. This can be used for
* incrementing the offset to the next key / value pair.
*/
-static int iscsi_parse_text_key_value_pair(iscsi_login_kvp *key_value_pairs, const uint8_t *packet_data, const uint32_t len)
+static int iscsi_parse_text_key_value_pair(iscsi_negotiation_kvp *key_value_pairs, const char *packet_data, const uint32_t len)
{
- uint key_val_len = (uint) strnlen( (char *) packet_data, len );
- const uint8_t *key_end = memchr( packet_data, '=', key_val_len );
+ int key_val_len = (int) strnlen( packet_data, len );
+ const char *key_end = memchr( packet_data, '=', key_val_len );
- if ( key_val_len == len ) {
+ if ( key_val_len == (int)len ) {
logadd( LOG_DEBUG1, "iscsi_parse_text_key_value_pair: Final key/value pair not null-terminated, not spec compliant, aborting" );
return -1;
}
@@ -352,18 +237,26 @@ static int iscsi_parse_text_key_value_pair(iscsi_login_kvp *key_value_pairs, con
}
#define COPY_KVP(type, key) \
- else if ( strncmp( (const char *)packet_data, #key, key_len ) == 0 ) iscsi_copy_kvp_ ## type ( #key, &key_value_pairs->key, key_end + 1 )
+ else if ( strncmp( packet_data, #key, key_len ) == 0 ) iscsi_copy_kvp_ ## type ( #key, &key_value_pairs->key, key_end + 1 )
if ( 0 ) {}
COPY_KVP( int, MaxRecvDataSegmentLength );
COPY_KVP( int, MaxBurstLength );
COPY_KVP( int, FirstBurstLength );
+ COPY_KVP( int, MaxConnections );
+ COPY_KVP( int, ErrorRecoveryLevel );
+ COPY_KVP( str, SessionType );
COPY_KVP( str, AuthMethod );
+ COPY_KVP( str, SendTargets );
+ COPY_KVP( str, HeaderDigest );
+ COPY_KVP( str, DataDigest );
+ COPY_KVP( str, InitiatorName );
+ COPY_KVP( str, TargetName );
else {
- logadd( LOG_DEBUG1, "iscsi_parse_text_key_value_pair: Unknown option: '%.*s'", (int)key_len, (const char*)packet_data );
+ logadd( LOG_DEBUG1, "iscsi_parse_text_key_value_pair: Unknown option: '%.*s'", (int)key_len, packet_data );
}
-#undef COPY_KVP_INT
+#undef COPY_KVP
return (int)key_val_len;
}
@@ -375,84 +268,35 @@ static int iscsi_parse_text_key_value_pair(iscsi_login_kvp *key_value_pairs, con
* data amd puts the extracted data into a hash map to be used by
* the iSCSI implementation.
*
- * @param[in] key_value_pairs Pointer to hash map that should contain all
+ * @param[in] pairs struct to write all key-value-pair options from packet to
* extracted keys and pairs. May NOT be NULL, so take caution.
* @param[in] packet_data Pointer to first key and value pair to
* be parsed. NULL is an illegal value here, so be careful.
* @param[in] len Length of the remaining packet data.
- * @param[in] c_bit Non-zero value of C bit was set in previously.
- * @param[in] partial_pairs Array of partial pair pointers in
- * case C bit was set (multiple iSCSI packets for text data).
* @retval -1 An error occured during parsing key.
* @retval 0 Key and value pair was parsed successfully and was added to
* hash map.
*/
-static int iscsi_parse_login_key_value_pairs(iscsi_login_kvp *key_value_pairs, const uint8_t *packet_data, uint len, int c_bit, uint8_t **partial_pairs)
+static int iscsi_parse_login_key_value_pairs(iscsi_negotiation_kvp *pairs, const uint8_t *packet_data, uint len)
{
+ memset( pairs, -1 , sizeof(*pairs) );
+ pairs->SessionType = NULL;
+ pairs->AuthMethod = NULL;
+ pairs->SendTargets = NULL;
+ pairs->HeaderDigest = NULL;
+ pairs->DataDigest = NULL;
+ pairs->InitiatorName = NULL;
+ pairs->TargetName = NULL;
+
if ( len == 0U )
return 0; // iSCSI specs don't allow zero length
- if ( (partial_pairs != NULL) && (*partial_pairs != NULL) ) { // Strip partial text parameters in case C bit was enabled previously
- uint key_val_pair_len;
-
- for (key_val_pair_len = 0; (key_val_pair_len < len) && packet_data[key_val_pair_len] != '\0'; key_val_pair_len++) {
- }
-
- uint8_t *tmp_partial_buf = iscsi_sprintf_alloc( "%s%s", *partial_pairs, (const char *) packet_data );
-
- if ( tmp_partial_buf == NULL )
- return -1;
-
- const int rc = iscsi_parse_text_key_value_pair( key_value_pairs, tmp_partial_buf, (uint32_t) (key_val_pair_len + strlen( (char *) *partial_pairs )) );
- free( tmp_partial_buf );
-
- if ( rc < 0 )
- return -1;
-
- free( *partial_pairs );
- *partial_pairs = NULL;
-
- packet_data += (key_val_pair_len + 1);
- len -= (key_val_pair_len + 1);
- }
-
- if ( c_bit ) { // Strip partial parameters in case C bit was enabled previousley
- if ( partial_pairs == NULL ) {
- logadd( LOG_ERROR, "iscsi_parse_key_value_pairs: C bit set but missing partial parameter" );
-
- return -1;
- }
-
- uint key_val_pair_len;
-
- for (key_val_pair_len = (len - 1U); (packet_data[key_val_pair_len] != '\0') && (key_val_pair_len > 0U); key_val_pair_len--) {
- }
-
- if ( key_val_pair_len != 0U )
- key_val_pair_len++; // NUL char found, don't copy to target buffer'
-
- *partial_pairs = (uint8_t *) malloc( ((len - key_val_pair_len) + 1U) );
-
- if ( *partial_pairs == NULL ) {
- logadd( LOG_ERROR, "iscsi_parse_key_value_pairs: Out of memory allocating partial parameter" );
-
- return -1;
- }
-
- memcpy( *partial_pairs, &packet_data[key_val_pair_len], (len - key_val_pair_len) );
-
- if ( key_val_pair_len != 0U )
- len = (key_val_pair_len - 1U);
- else
- return 0;
- }
-
int offset = 0;
while ( ((uint) offset < len) && (packet_data[offset] != '\0') ) {
- const int rc = iscsi_parse_text_key_value_pair( key_value_pairs, (packet_data + offset), (len - offset) );
+ const int rc = iscsi_parse_text_key_value_pair( pairs, (const char *)(packet_data + offset), (len - offset) );
- if ( rc < 0 )
+ if ( rc <= 0 )
return -1;
offset += rc;
@@ -478,7 +322,7 @@ static int iscsi_parse_login_key_value_pairs(iscsi_login_kvp *key_value_pairs, c
*/
static iscsi_task *iscsi_task_create(iscsi_connection *conn)
{
- iscsi_task *task = (iscsi_task *) malloc( sizeof(struct iscsi_task) );
+ iscsi_task *task = malloc( sizeof(struct iscsi_task) );
if ( task == NULL ) {
logadd( LOG_ERROR, "iscsi_task_create: Out of memory while allocating iSCSI task" );
@@ -497,9 +341,6 @@ static iscsi_task *iscsi_task_create(iscsi_connection *conn)
task->des_data_xfer_pos = 0UL;
task->des_data_xfer_len = 0UL;
task->data_sn = 0UL;
- task->scsi_data_out_cnt = 0UL;
-
- conn->task_cnt++;
iscsi_scsi_task_create( &task->scsi_task );
task->scsi_task.connection = conn;
@@ -521,7 +362,6 @@ static void iscsi_task_destroy(iscsi_task *task)
return;
free( task->scsi_task.buf );
- task->conn->task_cnt--;
free( task );
}
@@ -548,7 +388,7 @@ static void iscsi_task_destroy(iscsi_task *task)
*/
static uint32_t iscsi_scsi_data_in_send(iscsi_connection *conn, iscsi_task *task, const uint32_t pos, const uint32_t len, const uint32_t res_cnt, const uint32_t data_sn, const int8_t flags, bool immediate)
{
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, len, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, len );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_scsi_data_in_send: Out of memory while allocating iSCSI SCSI Data In response PDU" );
@@ -706,7 +546,7 @@ static void iscsi_task_response(iscsi_connection *conn, iscsi_task *task, iscsi_
}
const uint32_t ds_len = (task->scsi_task.sense_data_len != 0U) ? (task->scsi_task.sense_data_len + offsetof(struct iscsi_scsi_ds_cmd_data, sense_data)) : 0UL;
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, ds_len, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, ds_len );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_task_response: Out of memory while allocating iSCSI SCSI response PDU" );
@@ -771,11 +611,7 @@ static void iscsi_task_response(iscsi_connection *conn, iscsi_task *task, iscsi_
}
/**
- * @brief Allocates and initializes a SCSI task.
- *
- * THis function assocates the callback
- * functions to the SCSI task and sets
- * the reference count to 1.
+ * @brief Initializes a SCSI task.
*
* @param[in] scsi_task Pointer to SCSI task. This
* may NOT be NULL, so be careful.
@@ -793,8 +629,6 @@ static void iscsi_scsi_task_create(iscsi_scsi_task *scsi_task)
scsi_task->xfer_len = 0UL;
scsi_task->sense_data_len = 0U;
scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
- scsi_task->task_mgmt_func = ISCSI_TASK_MGMT_FUNC_REQ_FUNC_ABORT_TASK;
- scsi_task->task_mgmt_response = ISCSI_TASK_MGMT_FUNC_RESPONSE_FUNC_COMPLETE;
}
/**
@@ -892,44 +726,6 @@ static void iscsi_scsi_task_status_set(iscsi_scsi_task *scsi_task, const uint8_t
}
/**
- * @brief Copies iSCSI SCSI task sense data and status code.
- *
- * This function allocates, if necessary, a
- * SCSI sense data buffer and copies it over
- * from source or deallocates the sense data
- * buffer in case the source has no sense
- * data.
- *
- * @param[in] dst_scsi_task Pointer to iSCSI SCSI task to copy to.
- * May NOT be NULL, so be careful.
- * @param[in] src_scsi_task Pointer to iSCSI SCSI task to copy from.
- * NULL is NOT allowed here, take caution.
- * @return 0 on successful copy operation, a negative
- * error code otherwise.
- */
-static int iscsi_scsi_task_status_copy(iscsi_scsi_task *dst_scsi_task, const iscsi_scsi_task *src_scsi_task)
-{
- if ( dst_scsi_task->sense_data != NULL )
- free( dst_scsi_task->sense_data );
-
- if ( src_scsi_task->sense_data != NULL ) {
- dst_scsi_task->sense_data = malloc( src_scsi_task->sense_data_len );
-
- if ( dst_scsi_task == NULL )
- return -1;
-
- memcpy( dst_scsi_task->sense_data, src_scsi_task->sense_data, src_scsi_task->sense_data_len );
- } else {
- dst_scsi_task->sense_data = NULL;
- }
-
- dst_scsi_task->sense_data_len = src_scsi_task->sense_data_len;
- dst_scsi_task->status = src_scsi_task->status;
-
- return 0;
-}
-
-/**
* @brief Processes a iSCSI SCSI task with no LUN identifier.
*
* This function only generates a SCSI response
@@ -1065,60 +861,6 @@ static void iscsi_scsi_lun_task_run( iscsi_scsi_task *scsi_task, iscsi_pdu *pdu)
}
/**
- * @brief Checks whether an I/O feature is supported by a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties and queries only one I/O
- * feature at once.
- *
- * @param[in] image Pointer to DNBD3 image to check I/O
- * attributes for. May NOT be NULL, so be
- * careful.
- * @param[in] type I/O type to be checked for.
- * @retval true The DNBD3 image supports the I/O feature.
- * @retval false The I/O feature is NOT supported for the
- * DNBD3 image.
- */
-static inline bool iscsi_scsi_emu_io_type_is_supported(const dnbd3_image_t *image, const int type)
-{
- switch ( type ) {
- case ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE : {
- return true;
- }
- case ISCSI_SCSI_EMU_IO_TYPE_NO_ROTATION : {
- return true;
- }
- case ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY : {
- return false;
- }
- case ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT : {
- return true;
- }
- default : {
- return false;
- break;
- }
- }
-}
-
-/**
- * @brief Retrieves the bit shift of a physical block in bytes for a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties.
- *
- * @param[in] image Pointer to DNBD3 image to retrieve
- * the physical bit shift size. May NOT
- * be NULL, so be careful.
- * @return The physical block size in bytes as a
- * bit shift count.
- */
-static inline uint32_t iscsi_scsi_emu_physical_block_get_size_shift(const dnbd3_image_t *image)
-{
- return ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS;
-}
-
-/**
* @brief Retrieves the size of a physical block in bytes for a DNBD3 image.
*
* This function depends on DNBD3 image
@@ -1147,77 +889,7 @@ static inline uint32_t iscsi_scsi_emu_physical_block_get_size(const dnbd3_image_
*/
static inline uint64_t iscsi_scsi_emu_block_get_count(const dnbd3_image_t *image)
{
- return (image->virtualFilesize >> ISCSI_SCSI_EMU_BLOCK_SIZE_BITS);
-}
-
-/**
- * @brief Retrieves the bit shift of a logical block in bytes for a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties.
- *
- * @param[in] image Pointer to DNBD3 image to retrieve
- * the logical block bit shift size.
- * May NOT be NULL, so be careful.
- * @return The logical block size in bytes as a
- * bit shift count.
- */
-static inline uint32_t iscsi_scsi_emu_block_get_size_shift(const dnbd3_image_t *image)
-{
- return ISCSI_SCSI_EMU_BLOCK_SIZE_BITS;
-}
-
-/**
- * @brief Retrieves the size of a logical block in bytes for a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties.
- *
- * @param[in] image Pointer to DNBD3 image to retrieve
- * the logical block size. May NOT be NULL,
- * so be careful.
- * @return The logical block size in bytes.
- */
-static inline uint32_t iscsi_scsi_emu_block_get_size(const dnbd3_image_t *image)
-{
- return ISCSI_SCSI_EMU_BLOCK_SIZE;
-}
-
-/**
- * @brief Retrieves the bit shift ratio between logical and physical block size for a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties.
- *
- * @param[in] image Pointer to DNBD3 image to retrieve
- * the ratio between the logical and
- * physical block size. May NOT be
- * NULL, so be careful.
- * @return The ratio between logical and physical
- * block size as a logical bit shift
- * count.
- */
-static inline uint32_t iscsi_scsi_emu_block_get_ratio_shift(const dnbd3_image_t *image)
-{
- return (iscsi_scsi_emu_physical_block_get_size_shift(image) - iscsi_scsi_emu_block_get_size_shift(image));
-}
-
-/**
- * @brief Retrieves the ratio between logical and physical block size for a DNBD3 image.
- *
- * This function depends on DNBD3 image
- * properties.
- *
- * @param[in] image Pointer to DNBD3 image to retrieve
- * the ratio between the logical and
- * physical block size. May NOT be
- * NULL, so be careful.
- * @return The ratio between logical logical and physical
- * block size.
- */
-static inline uint32_t iscsi_scsi_emu_block_get_ratio(const dnbd3_image_t *image)
-{
- return (1UL << iscsi_scsi_emu_block_get_ratio_shift( image ));
+ return (image->virtualFilesize / ISCSI_SCSI_EMU_BLOCK_SIZE);
}
/**
@@ -1239,21 +911,12 @@ static inline uint32_t iscsi_scsi_emu_block_get_ratio(const dnbd3_image_t *image
* bytes is aligned to block size or a
* positive value if unaligned.
*/
-static uint64_t iscsi_scsi_emu_bytes_to_blocks(uint64_t *offset_blocks, uint64_t *num_blocks, const uint64_t offset_bytes, const uint64_t num_bytes, const uint32_t block_size)
+static uint64_t iscsi_scsi_emu_bytes_to_blocks(uint64_t *offset_blocks, uint64_t *num_blocks, const uint64_t offset_bytes, const uint64_t num_bytes)
{
- if ( iscsi_is_pow2( block_size ) ) {
- const uint32_t shift = iscsi_get_log2_of_pow2( block_size );
-
- *offset_blocks = (offset_bytes >> shift);
- *num_blocks = (num_bytes >> shift);
+ *offset_blocks = (offset_bytes / ISCSI_SCSI_EMU_BLOCK_SIZE);
+ *num_blocks = (num_bytes / ISCSI_SCSI_EMU_BLOCK_SIZE);
- return ((offset_bytes - (*offset_blocks << shift)) | (num_bytes - (*num_blocks << shift)));
- }
-
- *offset_blocks = (offset_bytes / block_size);
- *num_blocks = (num_bytes / block_size);
-
- return ((offset_bytes % block_size) | (num_bytes % block_size));
+ return ((offset_bytes % ISCSI_SCSI_EMU_BLOCK_SIZE) | (num_bytes % ISCSI_SCSI_EMU_BLOCK_SIZE));
}
/**
@@ -1267,22 +930,13 @@ static uint64_t iscsi_scsi_emu_bytes_to_blocks(uint64_t *offset_blocks, uint64_t
* careful.
* @param[in] offset_blocks Offset in blocks.
* @param[in] num_blocks Number of blocks.
- * @param[in] block_size Block size in bytes.
* @return Number of blocks in bytes.
*/
-static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size)
+static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uint64_t offset_blocks, const uint64_t num_blocks)
{
- if ( iscsi_is_pow2( block_size ) ) {
- const uint32_t shift = iscsi_get_log2_of_pow2( block_size );
-
- *offset_bytes = (offset_blocks << shift);
+ *offset_bytes = (offset_blocks * ISCSI_SCSI_EMU_BLOCK_SIZE);
- return (num_blocks << shift);
- }
-
- *offset_bytes = (offset_blocks * block_size);
-
- return (num_blocks * block_size);
+ return (num_blocks * ISCSI_SCSI_EMU_BLOCK_SIZE);
}
/**
@@ -1301,11 +955,11 @@ static uint64_t iscsi_scsi_emu_blocks_to_bytes(uint64_t *offset_bytes, const uin
* uplink_request().
* @param[in] buffer Data for requested range.
*/
-static void iscsi_uplink_callback(void *data, uint64_t handle, uint64_t start UNUSED, uint32_t length, const char *buffer)
+static void iscsi_uplink_callback(void *data, uint64_t handle UNUSED, uint64_t start UNUSED, uint32_t length, const char *buffer)
{
iscsi_scsi_task *scsi_task = (iscsi_scsi_task *) data;
- memcpy( (uint8_t *) handle, buffer, length );
+ memcpy( scsi_task->buf, buffer, length );
pthread_mutex_lock( &scsi_task->uplink_mutex );
pthread_cond_signal( &scsi_task->uplink_cond );
@@ -1323,9 +977,6 @@ static void iscsi_uplink_callback(void *data, uint64_t handle, uint64_t start UN
* @param[in] scsi_task Pointer to iSCSI SCSI task which
* executes the I/O read operation, may
* NOT be NULL, so be careful.
- * @param[in] buf Pointer to buffer where to store
- * the read data. NULL is NOT allowed
- * here, take caution.
* @param[in] image Pointer to DNBD3 image to read
* data from and may NOT be NULL, so
* be careful.
@@ -1335,10 +986,10 @@ static void iscsi_uplink_callback(void *data, uint64_t handle, uint64_t start UN
* @return 0 on successful operation, a negative
* error code otherwise.
*/
-static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, uint8_t *buf, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks, const uint32_t block_size)
+static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, dnbd3_image_t *image, const uint64_t offset_blocks, const uint64_t num_blocks)
{
uint64_t offset_bytes;
- const uint64_t num_bytes = iscsi_scsi_emu_blocks_to_bytes( &offset_bytes, offset_blocks, num_blocks, block_size );
+ const uint64_t num_bytes = iscsi_scsi_emu_blocks_to_bytes( &offset_bytes, offset_blocks, num_blocks );
dnbd3_cache_map_t *cache = ref_get_cachemap( image );
bool readFromFile;
@@ -1359,7 +1010,7 @@ static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, uint8_t *bu
pthread_cond_init( &scsi_task->uplink_cond, NULL );
pthread_mutex_lock( &scsi_task->uplink_mutex );
- if ( !uplink_request( image, scsi_task, iscsi_uplink_callback, (uint64_t) buf, offset_bytes, num_bytes ) ) {
+ if ( !uplink_request( image, scsi_task, iscsi_uplink_callback, 0, offset_bytes, num_bytes ) ) {
pthread_mutex_unlock( &scsi_task->uplink_mutex );
logadd( LOG_DEBUG1, "Could not relay uncached request to upstream proxy for image %s:%d",
@@ -1379,7 +1030,7 @@ static int iscsi_scsi_emu_io_blocks_read(iscsi_scsi_task *scsi_task, uint8_t *bu
bool success;
if ( readFromFile ) {
- const int64_t len = pread( image->readFd, buf, (size_t) num_bytes, offset_bytes );
+ const int64_t len = pread( image->readFd, scsi_task->buf, (size_t) num_bytes, offset_bytes );
success = ((uint64_t) len == num_bytes);
} else {
success = true;
@@ -1420,15 +1071,21 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
{
scsi_task->xfer_pos = 0UL;
+ if ( (flags & ISCSI_SCSI_EMU_BLOCK_FLAGS_WRITE) != 0 ) {
+ iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
+
+ return ISCSI_SCSI_TASK_RUN_COMPLETE;
+ }
+
if ( (scsi_task->flags & (ISCSI_SCSI_TASK_FLAGS_XFER_READ | ISCSI_SCSI_TASK_FLAGS_XFER_WRITE)) == (ISCSI_SCSI_TASK_FLAGS_XFER_READ | ISCSI_SCSI_TASK_FLAGS_XFER_WRITE) ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
return ISCSI_SCSI_TASK_RUN_COMPLETE;
}
- const uint64_t block_count = iscsi_scsi_emu_block_get_count( image );
+ const uint64_t imgBlockCount = iscsi_scsi_emu_block_get_count( image );
- if ( (block_count <= lba) || ((block_count - lba) < xfer_len) ) {
+ if ( (imgBlockCount <= lba) || ((imgBlockCount - lba) < xfer_len) ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
return ISCSI_SCSI_TASK_RUN_COMPLETE;
@@ -1440,8 +1097,7 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
return ISCSI_SCSI_TASK_RUN_COMPLETE;
}
- const uint32_t block_size = iscsi_scsi_emu_block_get_size( image );
- const uint32_t max_xfer_len = ISCSI_MAX_DS_SIZE / block_size;
+ const uint32_t max_xfer_len = ISCSI_MAX_DS_SIZE / ISCSI_SCSI_EMU_BLOCK_SIZE;
if ( xfer_len > max_xfer_len ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
@@ -1449,16 +1105,10 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
return ISCSI_SCSI_TASK_RUN_COMPLETE;
}
- if ( (flags & ISCSI_SCSI_EMU_BLOCK_FLAGS_WRITE) != 0 ) {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
-
- return ISCSI_SCSI_TASK_RUN_COMPLETE;
- }
-
uint64_t offset_blocks;
uint64_t num_blocks;
- if ( iscsi_scsi_emu_bytes_to_blocks( &offset_blocks, &num_blocks, scsi_task->pos, scsi_task->len, block_size ) != 0ULL ) {
+ if ( iscsi_scsi_emu_bytes_to_blocks( &offset_blocks, &num_blocks, scsi_task->pos, scsi_task->len ) != 0ULL ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
return ISCSI_SCSI_TASK_RUN_COMPLETE;
@@ -1468,23 +1118,17 @@ static int iscsi_scsi_emu_block_read_write(dnbd3_image_t *image, iscsi_scsi_task
int rc;
- if ( (flags & ISCSI_SCSI_EMU_BLOCK_FLAGS_WRITE) == 0 ) {
- scsi_task->buf = (uint8_t *) malloc( scsi_task->len );
-
- if ( scsi_task->buf == NULL ) {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR,
- ISCSI_SCSI_ASC_INTERNAL_TARGET_FAIL, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE );
-
- return ISCSI_SCSI_TASK_RUN_COMPLETE;
- }
+ scsi_task->buf = (uint8_t *) malloc( scsi_task->len );
- rc = iscsi_scsi_emu_io_blocks_read( scsi_task, scsi_task->buf, image, offset_blocks, num_blocks, block_size );
- } else {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_DATA_PROTECT, ISCSI_SCSI_ASC_WRITE_PROTECTED, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
+ if ( scsi_task->buf == NULL ) {
+ iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR,
+ ISCSI_SCSI_ASC_INTERNAL_TARGET_FAIL, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE );
return ISCSI_SCSI_TASK_RUN_COMPLETE;
}
+ rc = iscsi_scsi_emu_io_blocks_read( scsi_task, image, offset_blocks, num_blocks );
+
if ( rc < 0 ) {
if ( rc == -ENOMEM ) {
iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR,
@@ -1532,8 +1176,6 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
xfer_len = 256UL;
return iscsi_scsi_emu_block_read_write( image, scsi_task, lba, xfer_len, 0 );
-
- break;
}
case ISCSI_SCSI_OPCODE_READ10 : {
const iscsi_scsi_cdb_read_write_10 *cdb_read_write_10 = (iscsi_scsi_cdb_read_write_10 *) scsi_task->cdb;
@@ -1542,8 +1184,6 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
xfer_len = iscsi_get_be16(cdb_read_write_10->xfer_len);
return iscsi_scsi_emu_block_read_write( image, scsi_task, lba, xfer_len, 0 );
-
- break;
}
case ISCSI_SCSI_OPCODE_READ12 : {
const iscsi_scsi_cdb_read_write_12 *cdb_read_write_12 = (iscsi_scsi_cdb_read_write_12 *) scsi_task->cdb;
@@ -1552,8 +1192,6 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
xfer_len = iscsi_get_be32(cdb_read_write_12->xfer_len);
return iscsi_scsi_emu_block_read_write( image, scsi_task, lba, xfer_len, 0 );
-
- break;
}
case ISCSI_SCSI_OPCODE_READ16 : {
const iscsi_scsi_cdb_read_write_16 *cdb_read_write_16 = (iscsi_scsi_cdb_read_write_16 *) scsi_task->cdb;
@@ -1562,8 +1200,6 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
xfer_len = iscsi_get_be32(cdb_read_write_16->xfer_len);
return iscsi_scsi_emu_block_read_write( image, scsi_task, lba, xfer_len, 0 );
-
- break;
}
case ISCSI_SCSI_OPCODE_READCAPACITY10 : {
iscsi_scsi_read_capacity_10_parameter_data_packet *buf = (iscsi_scsi_read_capacity_10_parameter_data_packet *) malloc( sizeof(struct iscsi_scsi_read_capacity_10_parameter_data_packet) );
@@ -1581,9 +1217,7 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
else
iscsi_put_be32( (uint8_t *) &buf->lba, (uint32_t) lba );
- xfer_len = iscsi_scsi_emu_block_get_size( image );
-
- iscsi_put_be32( (uint8_t *) &buf->block_len, xfer_len );
+ iscsi_put_be32( (uint8_t *) &buf->block_len, ISCSI_SCSI_EMU_BLOCK_SIZE );
uint len = scsi_task->len;
@@ -1599,53 +1233,41 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task)
case ISCSI_SCSI_OPCODE_SERVICE_ACTION_IN_16 : {
const iscsi_scsi_cdb_service_action_in_16 *cdb_servce_in_action_16 = (iscsi_scsi_cdb_service_action_in_16 *) scsi_task->cdb;
- switch ( ISCSI_SCSI_CDB_SERVICE_ACTION_IN_16_GET_ACTION(cdb_servce_in_action_16->action) ) {
- case ISCSI_SCSI_CDB_SERVICE_ACTION_IN_16_ACTION_READ_CAPACITY_16 : {
- iscsi_scsi_service_action_in_16_parameter_data_packet *buf = (iscsi_scsi_service_action_in_16_parameter_data_packet *) malloc( sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet) );
-
- if ( buf == NULL ) {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY );
-
- return ISCSI_SCSI_TASK_RUN_COMPLETE;
- }
-
- lba = iscsi_scsi_emu_block_get_count( image ) - 1ULL;
- xfer_len = iscsi_scsi_emu_block_get_size( image );
+ if ( ISCSI_SCSI_CDB_SERVICE_ACTION_IN_16_GET_ACTION(cdb_servce_in_action_16->action)
+ != ISCSI_SCSI_CDB_SERVICE_ACTION_IN_16_ACTION_READ_CAPACITY_16 ) {
+ return ISCSI_SCSI_TASK_RUN_UNKNOWN;
+ }
+ iscsi_scsi_service_action_in_16_parameter_data_packet *buf = (iscsi_scsi_service_action_in_16_parameter_data_packet *) malloc( sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet) );
- iscsi_put_be64( (uint8_t *) &buf->lba, lba );
- iscsi_put_be32( (uint8_t *) &buf->block_len, xfer_len );
+ if ( buf == NULL ) {
+ iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY );
- buf->flags = 0;
+ return ISCSI_SCSI_TASK_RUN_COMPLETE;
+ }
- const uint8_t exponent = (uint8_t) iscsi_scsi_emu_block_get_ratio_shift( image );
+ lba = iscsi_scsi_emu_block_get_count( image ) - 1ULL;
- buf->exponents = ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_PUT_LBPPB_EXPONENT((exponent <= ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LBPPB_EXPONENT_MASK) ? exponent : 0U);
+ iscsi_put_be64( (uint8_t *) &buf->lba, lba );
+ iscsi_put_be32( (uint8_t *) &buf->block_len, ISCSI_SCSI_EMU_BLOCK_SIZE );
- if ( iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_UNMAP ) )
- iscsi_put_be16( (uint8_t *) &buf->lbp_lalba, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LBPME );
- else
- buf->lbp_lalba = 0U;
+ buf->flags = 0;
- buf->reserved[0] = 0ULL;
- buf->reserved[1] = 0ULL;
+ const uint8_t exponent = ISCSI_SCSI_EMU_BLOCK_DIFF_SHIFT;
- uint len = cdb_servce_in_action_16->alloc_len;
+ buf->exponents = ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_PUT_LBPPB_EXPONENT((exponent <= ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LBPPB_EXPONENT_MASK) ? exponent : 0U);
- if ( len > sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet) )
- len = sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet); // TODO: Check whether scatter data is required
+ buf->lbp_lalba = 0U;
+ buf->reserved[0] = 0ULL;
+ buf->reserved[1] = 0ULL;
- scsi_task->buf = (uint8_t *) buf;
- scsi_task->xfer_pos = len;
- scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
+ uint len = cdb_servce_in_action_16->alloc_len;
- break;
- }
- default : {
- return ISCSI_SCSI_TASK_RUN_UNKNOWN;
+ if ( len > sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet) )
+ len = sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet); // TODO: Check whether scatter data is required
- break;
- }
- }
+ scsi_task->buf = (uint8_t *) buf;
+ scsi_task->xfer_pos = len;
+ scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
break;
}
@@ -1958,7 +1580,7 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
vpd_page_block_limits_inquiry_data_pkt->flags = 0;
- uint32_t blocks = (ISCSI_MAX_DS_SIZE >> iscsi_scsi_emu_block_get_size_shift( image ));
+ uint32_t blocks = (ISCSI_MAX_DS_SIZE / ISCSI_SCSI_EMU_BLOCK_SIZE);
vpd_page_block_limits_inquiry_data_pkt->max_cmp_write_len = (uint8_t) blocks;
@@ -2027,7 +1649,7 @@ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task
const uint8_t pti = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT) | ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE);
std_inquiry_data_pkt->basic_inquiry.peripheral_type_id = pti;
- std_inquiry_data_pkt->basic_inquiry.peripheral_type_mod_flags = (int8_t) (iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE ) ? ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FLAGS_REMOVABLE_MEDIA : 0);
+ std_inquiry_data_pkt->basic_inquiry.peripheral_type_mod_flags = 0;
std_inquiry_data_pkt->basic_inquiry.version = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_VERSION_ANSI(ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC3);
std_inquiry_data_pkt->basic_inquiry.response_data_fmt_flags = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_RESPONSE_DATA_FMT_FLAGS(ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_SCSI_2) | ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_HISUP;
@@ -2329,9 +1951,6 @@ static int iscsi_scsi_emu_primary_mode_sense_page(dnbd3_image_t *image, iscsi_sc
iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page );
- if ( (mode_sense_mode_page_pkt != NULL) && iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE ) && (pc != ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES) )
- mode_sense_caching_mode_page_pkt->flags |= ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_WCE;
-
if ( (mode_sense_mode_page_pkt != NULL) && (pc != ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES) )
mode_sense_caching_mode_page_pkt->flags |= ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_RCD;
@@ -2492,21 +2111,24 @@ static int iscsi_scsi_emu_primary_mode_sense(dnbd3_image_t *image, iscsi_scsi_ta
if ( hdr_len == sizeof(struct iscsi_scsi_mode_sense_6_parameter_header_data_packet) ) {
mode_sense_6_parameter_hdr_data_pkt->mode_data_len = (uint8_t) (alloc_len - sizeof(uint8_t));
mode_sense_6_parameter_hdr_data_pkt->medium_type = 0U;
- mode_sense_6_parameter_hdr_data_pkt->flags = (int8_t) ((iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY ) || iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT )) ? ISCSI_SCSI_MODE_SENSE_6_PARAM_HDR_DATA_FLAGS_WP : 0);
+ mode_sense_6_parameter_hdr_data_pkt->flags = ISCSI_SCSI_MODE_SENSE_6_PARAM_HDR_DATA_FLAGS_WP;
mode_sense_6_parameter_hdr_data_pkt->block_desc_len = (uint8_t) block_desc_len;
- } else {
+ } else if ( hdr_len == sizeof(struct iscsi_scsi_mode_sense_10_parameter_header_data_packet) ) {
iscsi_scsi_mode_sense_10_parameter_header_data_packet *mode_sense_10_parameter_hdr_data_pkt = (iscsi_scsi_mode_sense_10_parameter_header_data_packet *) mode_sense_6_parameter_hdr_data_pkt;
iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->mode_data_len, (uint16_t) (alloc_len - sizeof(uint16_t)) );
mode_sense_10_parameter_hdr_data_pkt->medium_type = 0U;
- mode_sense_10_parameter_hdr_data_pkt->flags = (int8_t) ((iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_PHYSICAL_READ_ONLY ) || iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_WRITE_PROTECT )) ? ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_FLAGS_WP : 0);
+ mode_sense_10_parameter_hdr_data_pkt->flags = ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_FLAGS_WP;
mode_sense_10_parameter_hdr_data_pkt->long_lba = (uint8_t) long_lba;
mode_sense_10_parameter_hdr_data_pkt->reserved = 0U;
iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->block_desc_len, (uint16_t) block_desc_len );
+ } else {
+ logadd( LOG_DEBUG1, "iscsi_scsi_emu_primary_mode_sense: invalid parameter header length %u", hdr_len );
+ return -1;
}
const uint64_t num_blocks = iscsi_scsi_emu_block_get_count( image );
- const uint32_t block_size = iscsi_scsi_emu_block_get_size( image );
+ const uint32_t block_size = ISCSI_SCSI_EMU_BLOCK_SIZE;
if ( block_desc_len == sizeof(struct iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet) ) {
iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet *lba_parameter_block_desc = (iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet *) (((uint8_t *) mode_sense_6_parameter_hdr_data_pkt) + hdr_len);
@@ -2641,62 +2263,6 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task)
break;
}
- case ISCSI_SCSI_OPCODE_MODESELECT6 : {
- const iscsi_scsi_cdb_mode_select_6 *cdb_mode_select_6 = (iscsi_scsi_cdb_mode_select_6 *) scsi_task->cdb;
-
- alloc_len = cdb_mode_select_6->param_list_len;
-
- if ( alloc_len == 0U )
- break;
-
- rc = iscsi_scsi_emu_check_len( scsi_task, alloc_len, sizeof(struct iscsi_scsi_mode_select_6_parameter_list_packet) );
-
- if ( rc < 0 )
- break;
-
- len = scsi_task->len;
-
- if ( alloc_len < sizeof(struct iscsi_scsi_mode_select_6_parameter_list_packet) )
- alloc_len = sizeof(struct iscsi_scsi_mode_select_6_parameter_list_packet);
-
- rc = iscsi_scsi_emu_check_len( scsi_task, len, alloc_len );
-
- if ( rc < 0 )
- break;
-
- scsi_task->xfer_pos = alloc_len;
- scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
-
- break;
- }
- case ISCSI_SCSI_OPCODE_MODESELECT10 : {
- const iscsi_scsi_cdb_mode_select_10 *cdb_mode_select_10 = (iscsi_scsi_cdb_mode_select_10 *) scsi_task->cdb;
-
- alloc_len = iscsi_get_be16(cdb_mode_select_10->param_list_len);
-
- if ( alloc_len == 0U )
- break;
-
- rc = iscsi_scsi_emu_check_len( scsi_task, alloc_len, sizeof(struct iscsi_scsi_mode_select_10_parameter_list_packet) );
-
- if ( rc < 0 )
- break;
-
- len = scsi_task->len;
-
- if ( alloc_len < sizeof(struct iscsi_scsi_mode_select_10_parameter_list_packet) )
- alloc_len = sizeof(struct iscsi_scsi_mode_select_10_parameter_list_packet);
-
- rc = iscsi_scsi_emu_check_len( scsi_task, len, alloc_len );
-
- if ( rc < 0 )
- break;
-
- scsi_task->xfer_pos = alloc_len;
- scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
-
- break;
- }
case ISCSI_SCSI_OPCODE_MODESENSE6 : {
const iscsi_scsi_cdb_mode_sense_6 *cdb_mode_sense_6 = (iscsi_scsi_cdb_mode_sense_6 *) scsi_task->cdb;
@@ -2796,53 +2362,9 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task)
break;
}
- case ISCSI_SCSI_OPCODE_REQUESTSENSE : {
- const iscsi_scsi_cdb_req_sense *cdb_req_sense = (iscsi_scsi_cdb_req_sense *) scsi_task->cdb;
-
- if ( (cdb_req_sense->flags & ISCSI_SCSI_CDB_REQ_SENSE_FLAGS_DESC) != 0 ) {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
-
- break;
- }
-
- alloc_len = cdb_req_sense->alloc_len;
-
- iscsi_scsi_task_sense_data_build( scsi_task, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
-
- len = scsi_task->sense_data_len;
-
- if ( len > 0U ) {
- iscsi_scsi_sense_data_check_cond_packet *sense_data = malloc( len );
-
- if ( sense_data == NULL ) {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY );
-
- break;
- }
-
- memcpy( sense_data, scsi_task->sense_data, len );
-
- if ( len > alloc_len )
- len = alloc_len;
-
- scsi_task->buf = (uint8_t *) sense_data;
- }
-
- scsi_task->xfer_pos = len;
- scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
-
- break;
- }
- case ISCSI_SCSI_OPCODE_LOGSELECT :
- case ISCSI_SCSI_OPCODE_LOGSENSE : {
- iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE );
-
- break;
- }
case ISCSI_SCSI_OPCODE_TESTUNITREADY : {
scsi_task->xfer_pos = 0UL;
scsi_task->status = ISCSI_SCSI_STATUS_GOOD;
- logadd( LOG_WARNING, "UNIT READYYYYY" );
break;
}
@@ -2887,87 +2409,6 @@ static uint64_t iscsi_target_node_wwn_get(const uint8_t *name)
}
/**
- * @brief Extracts the DNBD3 image out of an iSCSI IQN string and opens the DNBD3 image.
- *
- * This function uses the : separator as
- * specified by the IQN standard.\n
- * If no colons are in the IQN string,
- * the complete string will be
- * considered the image file name.\n
- * The image file name is assumed
- * before the last colon and is
- * either directly opened or if
- * that fails, a WWN name by
- * IEEE Extended NAA is tried as
- * well.\n
- * The image revision is assumed
- * after the last colon.
- * @param[in] iqn Pointer to iSCSI IQN string. This
- * is not allowed to be NULL, so be careful.
- * @return Pointer to DNBD3 image if successful
- * operation or NULL if failed.
- */
-static dnbd3_image_t *iscsi_target_node_image_get(uint8_t *iqn)
-{
- uint8_t *image_name = iqn;
- uint8_t *image_rev = NULL;
- uint8_t *tmp = (uint8_t *) strchr( (char *) iqn, ':' );
-
- while ( tmp != NULL ) {
- tmp++;
-
- image_name = image_rev;
- image_rev = tmp;
- tmp = (uint8_t *) strchr( (char *) tmp, ':' );
- }
-
- if ( image_rev == NULL )
- image_rev = image_name;
-
- const uint len = (uint) (image_rev - image_name);
-
- if ( len > 0U ) {
- tmp = (uint8_t *) malloc( len );
-
- if ( tmp == NULL ) {
- logadd( LOG_ERROR, "iscsi_target_node_image_get: Out of memory while allocating DNBD3 image name for iSCSI target node" );
-
- return NULL;
- }
-
- memcpy( tmp, image_name, (len - 1) );
- tmp[len - 1] = '\0';
- } else {
- tmp = image_name;
- }
-
- const uint16_t rev = (uint16_t) ((len > 0U) ? atoi( (char *) image_rev ) : 0);
- dnbd3_image_t *image = image_getOrLoad( (char *) image_name, rev );
-
- if ( image == NULL ) {
- image = image_getOrLoad( (char *) tmp, rev );
-
- if ( image == NULL ) {
- if ( strncasecmp( (char *) image_name, ISCSI_TARGET_NODE_WWN_NAME_PREFIX, ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX) ) == 0 ) {
- uint64_t wwn = strtoull( (char *) (image_name + ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX)), NULL, 16 );
-
- image = image_getByWwn( wwn, rev, true );
-
- if ( image == NULL ) {
- wwn = strtoull( (char *) (tmp + ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX)), NULL, 16 );
- image = image_getByWwn( wwn, rev, true );
- }
- }
- }
- }
-
- if ( len > 0U )
- free( tmp );
-
- return image;
-}
-
-/**
* @brief Creates and initializes an iSCSI session.
*
* This function creates and initializes all relevant
@@ -2991,8 +2432,6 @@ static iscsi_session *iscsi_session_create(iscsi_connection *conn, const int ty
return NULL;
}
- session->flags = (ISCSI_SESSION_FLAGS_INIT_R2T | ISCSI_SESSION_FLAGS_DATA_PDU_IN_ORDER | ISCSI_SESSION_FLAGS_DATA_SEQ_IN_ORDER);
-
session->tsih = 0ULL;
session->type = type;
session->exp_cmd_sn = 0UL;
@@ -3037,26 +2476,9 @@ static iscsi_connection *iscsi_connection_create(dnbd3_client_t *client)
return NULL;
}
- conn->session = NULL;
-
- if ( conn->key_value_pairs == NULL ) {
- logadd( LOG_ERROR, "iscsi_create_connection: Out of memory while allocating iSCSI login text key / value pair hash map" );
-
- free( conn );
-
- return NULL;
- }
-
- conn->partial_pairs = NULL;
- conn->text_partial_pairs = NULL;
+ conn->session = NULL;
conn->pdu_processing = NULL;
conn->login_response_pdu = NULL;
- conn->target_send_total_size = 0U;
- conn->scsi_data_in_cnt = 0U;
- conn->scsi_data_out_cnt = 0U;
- conn->task_cnt = 0U;
- conn->header_digest = 0;
- conn->data_digest = 0;
conn->id = 0;
conn->client = client;
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_READY;
@@ -3070,7 +2492,6 @@ static iscsi_connection *iscsi_connection_create(dnbd3_client_t *client)
conn->init_task_tag = 0UL;
conn->target_xfer_tag = 0UL;
conn->stat_sn = 0UL;
- conn->exp_stat_sn = 0UL;
return conn;
}
@@ -3092,13 +2513,7 @@ static void iscsi_connection_destroy(iscsi_connection *conn)
{
if ( conn != NULL ) {
iscsi_session_destroy( conn->session );
-
- free ( conn->text_partial_pairs );
-
- if ( conn->partial_pairs != NULL ) {
- free ( conn->partial_pairs );
- }
-
+ iscsi_connection_pdu_destroy( conn->pdu_processing );
free( conn );
}
}
@@ -3120,31 +2535,14 @@ static int32_t iscsi_connection_read(const iscsi_connection *conn, uint8_t *buf,
if ( len == 0UL )
return 0L;
- const int32_t rc = (int32_t) recv( conn->client->sock, buf, (size_t) len, MSG_WAITALL );
-
- return ((rc > 0L) ? rc : (int32_t) ISCSI_CONNECT_PDU_READ_ERR_FATAL);
-}
-
-/**
- * @brief Writes data for the specified iSCSI connection to its TCP socket.
- *
- * The TCP socket is marked as non-blocking, so this function may not read
- * all data requested.
- *
- * Returns ISCSI_CONNECT_PDU_READ_ERR_FATAL if the operation
- * indicates a fatal error with the TCP connection (including
- * if the TCP connection was closed unexpectedly).
- *
- * Otherwise returns the number of bytes successfully written.
- */
-static int32_t iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf, const uint32_t len)
-{
- if ( len == 0UL )
- return 0L;
-
- const int32_t rc = (int32_t) sock_sendAll( conn->client->sock, buf, (size_t) len, ISCSI_CONNECT_SOCKET_WRITE_RETRIES );
+ int32_t rc;
+ do {
+ rc = (int32_t) recv( conn->client->sock, buf, (size_t) len, MSG_WAITALL );
+ } while ( rc == -1 && errno == EINTR );
- return ((rc > 0L) ? rc : (int32_t) ISCSI_CONNECT_PDU_READ_ERR_FATAL);
+ if ( rc == 0 )
+ return -1; // EOF
+ return rc;
}
/**
@@ -3154,8 +2552,7 @@ static int32_t iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf
* and value pair to an output DataSegment
* buffer and truncates if necessary.
*
- * @param[in] key_value_pair Pointer to key and value pair containing
- * its attributes.
+ * @param[in] number true = int, false = char*
* @param[in] key Pointer to key to be written to output
* buffer. NULL is NOT allowed, take caution.
* @param[in] value Pointer to value of the key that should
@@ -3167,20 +2564,20 @@ static int32_t iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf
* @param[in] pos Position of buffer in bytes to start
* writing to.
* @param[in] buflen Total length of buffer in bytes.
- * @return Bytes added to buffer, or negative
- * error code.
+ * @return -1 if buffer is already full, otherwise the number
+ * of bytes that are written or would have been written to
+ * the buffer.
*/
-static int iscsi_append_key_value_pair_packet(const char *key, const char *value, uint8_t *buf, const uint32_t pos, const uint32_t buflen)
+static int iscsi_append_key_value_pair_packet(const bool number, const char *key, const char *value, char *buf, const uint32_t pos, const uint32_t buflen)
{
if ( pos >= buflen )
return -1;
const ssize_t maxlen = buflen - pos;
- const ssize_t ret = snprintf( (char *) (buf + pos), maxlen, "%s=%s", key, value ) + 1;
-
- if ( ret > maxlen )
- return -1;
- return (int)ret;
+ if ( number ) {
+ return (int)snprintf( (buf + pos), maxlen, "%s=%d", key, (const int)(const size_t)value ) + 1;
+ }
+ return (int)snprintf( (buf + pos), maxlen, "%s=%s", key, value ) + 1;
}
@@ -3203,28 +2600,11 @@ static int iscsi_append_key_value_pair_packet(const char *key, const char *value
* @retval 0 All values have been updated successfully and
* the socket is still alive.
*/
-static int iscsi_connection_update_key_value_pairs(iscsi_connection *conn, iscsi_login_kvp *pairs)
+static void iscsi_connection_update_key_value_pairs(iscsi_connection *conn, iscsi_negotiation_kvp *pairs)
{
conn->session->opts.MaxBurstLength = CLAMP(pairs->MaxBurstLength, 512, ISCSI_MAX_DS_SIZE);
conn->session->opts.FirstBurstLength = CLAMP(pairs->FirstBurstLength, 512, pairs->MaxBurstLength);
conn->session->opts.MaxRecvDataSegmentLength = CLAMP(pairs->MaxRecvDataSegmentLength, 512, ISCSI_MAX_DS_SIZE);
-
- if ( conn->client->sock == -1 )
- return -1;
-
- int recv_buf_len = conn->session->opts.FirstBurstLength;
-
- if ( recv_buf_len < 4096 )
- recv_buf_len = 4096;
- else if ( recv_buf_len > 8192 )
- recv_buf_len = 8192;
-
- recv_buf_len += (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest + conn->data_digest); // BHS + maximum AHS size + header and data digest overhead
- recv_buf_len *= 16; // Receive up to 16 streams at once.
-
- setsockopt( conn->client->sock, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)); // Not being able to set the buffer is NOT fatal, so ignore error.
-
- return 0;
}
/**
@@ -3236,42 +2616,35 @@ static int iscsi_connection_update_key_value_pairs(iscsi_connection *conn, iscsi
* @param[in] conn Pointer to ISCSI connection to send the TCP/IP
* packet with. May NOT be NULL, so be
* careful.
- * @param[in] login_response_pdu Pointer to login response PDU to
+ * @param[in] resp_pdu Pointer to login response PDU to
* be sent via TCP/IP. NULL is NOT
* allowed here, take caution.
* @return 0 if the login response has been sent
* successfully, a negative error code otherwise.
*/
-static int iscsi_connection_pdu_login_response(iscsi_connection *conn, iscsi_pdu *login_response_pdu)
+static int iscsi_connection_pdu_login_response(iscsi_connection *conn, iscsi_pdu *resp_pdu)
{
- const uint32_t ds_len = login_response_pdu->ds_len;
-
- login_response_pdu->ds_len = login_response_pdu->len;
-
- iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) iscsi_connection_pdu_append( login_response_pdu, login_response_pdu->ahs_len, 0, ds_len, 0 );
+ iscsi_login_response_packet *login_response_pkt =
+ (iscsi_login_response_packet *) iscsi_connection_pdu_resize( resp_pdu, resp_pdu->ahs_len, resp_pdu->ds_write_pos );
login_response_pkt->version_max = ISCSI_VERSION_MAX;
login_response_pkt->version_active = ISCSI_VERSION_MAX;
- iscsi_put_be32( (uint8_t *) &login_response_pkt->total_ahs_len, ds_len ); // TotalAHSLength is always 0 and DataSegmentLength is 24-bit, so write in one step.
+ iscsi_put_be32( (uint8_t *) &login_response_pkt->total_ahs_len, resp_pdu->ds_len ); // TotalAHSLength is always 0 and DataSegmentLength is 24-bit, so write in one step.
iscsi_put_be32( (uint8_t *) &login_response_pkt->stat_sn, conn->stat_sn++ );
if ( conn->session != NULL ) { // TODO: Needed? MC/S?
iscsi_put_be32( (uint8_t *) &login_response_pkt->exp_cmd_sn, conn->session->exp_cmd_sn );
iscsi_put_be32( (uint8_t *) &login_response_pkt->max_cmd_sn, conn->session->max_cmd_sn );
} else {
- iscsi_put_be32( (uint8_t *) &login_response_pkt->exp_cmd_sn, login_response_pdu->cmd_sn );
- iscsi_put_be32( (uint8_t *) &login_response_pkt->max_cmd_sn, login_response_pdu->cmd_sn );
+ iscsi_put_be32( (uint8_t *) &login_response_pkt->exp_cmd_sn, resp_pdu->cmd_sn );
+ iscsi_put_be32( (uint8_t *) &login_response_pkt->max_cmd_sn, resp_pdu->cmd_sn );
}
if ( login_response_pkt->status_class != ISCSI_LOGIN_RESPONSE_STATUS_CLASS_SUCCESS )
login_response_pkt->flags &= (int8_t) ~(ISCSI_LOGIN_RESPONSE_FLAGS_TRANSIT | ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_MASK | ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_MASK );
- iscsi_connection_pdu_write( conn, login_response_pdu );
-
- if ( conn->state < ISCSI_CONNECT_STATE_EXITING && (conn->flags & ISCSI_CONNECT_FLAGS_FULL_FEATURE) != 0 ) {
- iscsi_connection_update_key_value_pairs( conn );
- }
+ iscsi_connection_pdu_write( conn, resp_pdu );
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -3295,8 +2668,6 @@ static int iscsi_connection_pdu_login_response_init(iscsi_pdu *login_response_pd
iscsi_login_req_packet *login_req_pkt = (iscsi_login_req_packet *) pdu->bhs_pkt;
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- login_response_pdu->ds_len = 0UL;
-
login_response_pkt->opcode = ISCSI_OPCODE_SERVER_LOGIN_RES;
login_response_pkt->flags = (int8_t) (login_req_pkt->flags & (ISCSI_LOGIN_REQ_FLAGS_TRANSIT | ISCSI_LOGIN_REQ_FLAGS_CONTINUE | ISCSI_LOGIN_REQ_FLAGS_CURRENT_STAGE_MASK));
@@ -3342,41 +2713,6 @@ static int iscsi_connection_pdu_login_response_init(iscsi_pdu *login_response_pd
}
/**
- * @brief Saves incoming key / value pairs from the client of a login request PDU.
- *
- * The login response structure has status detail
- * invalid login request type set in case of an error.
- *
- * @param[in] conn Pointer to iSCSI connection
- * used for key and value pair extraction.
- * @param[out] key_value_pairs Pointer to hash map which
- * stores all the parsed key and value pairs.
- * @param[in] login_response_pdu Pointer to iSCSI login response
- * PDU, may NOT be NULL, so be careful.
- * @param[in] pdu Pointer to iSCSI login request packet
- * PDU, may NOT be NULL, so be careful.
- * @retval -1 An error occured during parse of
- * key and value pairs (memory exhaustion).
- * @retval 0 All key and value pairs have been parsed successfully.
- */
-static int iscsi_connection_save_incoming_key_value_pairs(iscsi_connection *conn, iscsi_login_kvp *key_value_pairs, iscsi_pdu *login_response_pdu, const iscsi_pdu *pdu)
-{
- iscsi_login_req_packet *login_req_pkt = (iscsi_login_req_packet *) pdu->bhs_pkt;
- iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- const int rc = iscsi_parse_login_key_value_pairs( key_value_pairs, (uint8_t *) pdu->ds_cmd_data, pdu->ds_len,
- ((login_req_pkt->flags & ISCSI_LOGIN_REQ_FLAGS_CONTINUE) != 0), &conn->partial_pairs );
-
- if ( rc < 0 ) {
- login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC;
-
- return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_PARAMETER;
- }
-
- return ISCSI_CONNECT_PDU_READ_OK;
-}
-
-/**
* @brief Determines the session type of login.
*
* This function is used to retrieve the
@@ -3393,13 +2729,17 @@ static int iscsi_connection_save_incoming_key_value_pairs(iscsi_connection *conn
* otherwise. The output session 'type' is unchanged, if
* an invalid session type value was retrieved.
*/
-static int iscsi_login_check_session_type(iscsi_pdu *login_response_pdu, const char *type_str )
+static int iscsi_login_parse_session_type(iscsi_pdu *login_response_pdu, const char *type_str, int *type)
{
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- if ( type_str != NULL && strcasecmp( type_str, "Normal" ) == 0 )
+ if ( type_str != NULL && strcasecmp( type_str, "Normal" ) == 0 ) {
+ *type = ISCSI_SESSION_TYPE_NORMAL;
return ISCSI_CONNECT_PDU_READ_OK;
+ }
+ *type = ISCSI_SESSION_TYPE_INVALID;
+ logadd( LOG_DEBUG1, "Unsupported session type: %s", type_str );
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISSING_PARAMETER;
@@ -3426,11 +2766,60 @@ static int iscsi_login_check_session_type(iscsi_pdu *login_response_pdu, const c
* @return 0 if the check was successful or a negative
* error code otherwise.
*/
-static int iscsi_connection_login_check_target(iscsi_connection *conn, iscsi_pdu *login_response_pdu, uint8_t *target_name)
+static int iscsi_image_from_target(iscsi_connection *conn, iscsi_pdu *login_response_pdu, const char *target_name)
{
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- dnbd3_image_t *image = iscsi_target_node_image_get( target_name );
+ char *image_rev = NULL;
+ char *tmpbuf = strdup( target_name );
+ char *image_name = tmpbuf;
+ char *tmp = strchr( tmpbuf, ':' );
+
+ if ( tmpbuf == NULL ) {
+ logadd( LOG_ERROR, "iscsi_target_node_image_get: Out of memory while allocating DNBD3 image name for iSCSI target node" );
+ login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_SERVER_ERR;
+ login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_OUT_OF_RESOURCES;
+
+ return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
+ }
+
+ while ( tmp != NULL ) {
+ *tmp++ = '\0';
+ if ( image_rev != NULL ) {
+ image_name = image_rev;
+ }
+ image_rev = tmp;
+ tmp = strchr( tmp, ':' );
+ }
+
+ uint16_t rev = 0;
+ if ( image_rev != NULL ) {
+ char *end = NULL;
+ long rid = strtol( image_rev, &end, 10 );
+ if ( end == NULL || *end != '\0' || rid < 0 || rid > 0xFFFF ) {
+ logadd( LOG_DEBUG1, "iscsi_image_from_target: Invalid revision number (%s) in iSCSI target node name: '%s'", image_rev, target_name );
+ } else {
+ rev = (uint16_t)rid;
+ }
+ }
+ dnbd3_image_t *image = image_getOrLoad( image_name, rev );
+
+ if ( image == NULL && image_rev != NULL ) {
+ image = image_getOrLoad( image_rev, rev );
+ }
+
+ if ( image == NULL && strncasecmp( image_name, ISCSI_TARGET_NODE_WWN_NAME_PREFIX, ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX) ) == 0 ) {
+ uint64_t wwn = strtoull( (image_name + ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX)), NULL, 16 );
+
+ image = image_getByWwn( wwn, rev, true );
+
+ if ( image == NULL ) {
+ wwn = strtoull( (tmp + ISCSI_STRLEN(ISCSI_TARGET_NODE_WWN_NAME_PREFIX)), NULL, 16 );
+ image = image_getByWwn( wwn, rev, true );
+ }
+ }
+
+ free( tmpbuf );
if ( image == NULL ) {
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
@@ -3485,57 +2874,51 @@ static void iscsi_connection_login_response_reject(iscsi_pdu *login_response_pdu
* @param[in] conn Pointer to connection to link the PDU with.
* If this is NULL the connection has to be
* linked later.
- * @param[in] ahs_len Length of AHS packet data to be appended.
- * @param[in] header_digest_size Length of header digest. Currently,
- * only 0, in which case the header digest will
- * be removed, or 4 for CRC32C are allowed.
* @param[in] ds_len Length of DataSegment packet data to be appended.
* May not exceed 16MiB - 1 (16777215 bytes).
- * @param[in] data_digest_size Length of optional data digest (0 or
- * 4 for now) to add.
* @return Pointer to allocated and zero filled PDU or NULL
* in case of an error (usually memory exhaustion).
*/
-static iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn, const uint ahs_len, const int header_digest_size, const uint32_t ds_len, const int data_digest_size)
+static iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn, const uint32_t ds_len)
{
- if ( (ahs_len > ISCSI_MAX_AHS_SIZE) || ((header_digest_size != 0) && (header_digest_size != ISCSI_DIGEST_SIZE)) || ((data_digest_size != 0) && data_digest_size != ISCSI_DIGEST_SIZE) || (ds_len > ISCSI_MAX_DS_SIZE) )
+ if ( ds_len > ISCSI_MAX_DS_SIZE ) {
+ logadd( LOG_ERROR, "iscsi_pdu_create: Invalid DS length" );
return NULL;
+ }
- const uint32_t pkt_ds_len = ISCSI_ALIGN(ds_len, ISCSI_ALIGN_SIZE);
- const uint32_t len = (uint32_t) (sizeof(struct iscsi_bhs_packet) + (uint32_t) ahs_len + header_digest_size + pkt_ds_len + ((pkt_ds_len != 0UL) ? (uint32_t) data_digest_size : 0UL));
-
- iscsi_pdu *pdu = malloc( sizeof(struct iscsi_pdu) + len );
+ const uint32_t pkt_ds_len = ISCSI_ALIGN( ds_len, ISCSI_ALIGN_SIZE );
+ const uint32_t len = (uint32_t) ( sizeof(struct iscsi_bhs_packet) + pkt_ds_len );
+ iscsi_pdu *pdu = malloc( sizeof(struct iscsi_pdu) );
if ( pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_pdu_create: Out of memory while allocating iSCSI PDU" );
return NULL;
}
- iscsi_bhs_packet *bhs_pkt = (iscsi_bhs_packet *)(pdu + 1);
+ iscsi_bhs_packet *bhs_pkt = malloc( len );
+ if ( bhs_pkt == NULL ) {
+ free( pdu );
+ logadd( LOG_ERROR, "iscsi_pdu_create: Out of memory while allocating iSCSI BHS packet" );
+
+ return NULL;
+ }
pdu->bhs_pkt = bhs_pkt;
- pdu->ahs_pkt = (ahs_len != 0U) ? (iscsi_ahs_packet *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) ) : NULL;
- pdu->header_digest = (header_digest_size != 0) ? (iscsi_header_digest *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len) : NULL;
- pdu->ds_cmd_data = (pkt_ds_len != 0UL) ? (iscsi_scsi_ds_cmd_data *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len + header_digest_size) : NULL;
- pdu->data_digest = ((pkt_ds_len != 0uL) && (data_digest_size != 0)) ? (iscsi_data_digest *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len + header_digest_size + ISCSI_ALIGN(pkt_ds_len, ISCSI_ALIGN_SIZE)) : NULL;
+ pdu->ahs_pkt = NULL;
+ pdu->ds_cmd_data = (pkt_ds_len != 0UL) ? (iscsi_scsi_ds_cmd_data *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet)) : NULL;
pdu->task = NULL;
pdu->flags = 0;
pdu->bhs_pos = 0U;
- pdu->ahs_pos = 0U;
- pdu->ahs_len = ahs_len;
- pdu->header_digest_pos = 0U;
- pdu->header_digest_size = header_digest_size;
- pdu->ds_len = pkt_ds_len;
- pdu->pos = 0UL;
- pdu->len = pkt_ds_len;
- pdu->data_digest_pos = 0U;
- pdu->data_digest_size = data_digest_size;
- pdu->task_ref_cnt = 0U;
+ pdu->ahs_len = 0;
+ pdu->ds_len = ds_len;
+ pdu->ds_write_pos = 0;
pdu->cmd_sn = 0UL;
+ pdu->recv_pos = 0;
- if ( pkt_ds_len != 0UL )
+ if ( pkt_ds_len != 0UL ) {
memset( (((uint8_t *) pdu->ds_cmd_data) + ds_len), 0, (pkt_ds_len - ds_len) );
+ }
return pdu;
}
@@ -3552,6 +2935,9 @@ static iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn, const uint
*/
static void iscsi_connection_pdu_destroy(iscsi_pdu *pdu)
{
+ if ( pdu == NULL )
+ return;
+ free( pdu->bhs_pkt );
free( pdu );
}
@@ -3566,32 +2952,29 @@ static void iscsi_connection_pdu_destroy(iscsi_pdu *pdu)
* the packet data to. May NOT be NULL, so
* be careful.
* @param[in] ahs_len Length of AHS packet data to be appended.
- * @param[in] header_digest_size Length of header digest. Currently,
- * only 0, in which case the header digest will
- * be removed, or 4 for CRC32C are allowed.
* @param[in] ds_len Length of DataSegment packet data to be appended.
* May not exceed 16MiB - 1 (16777215 bytes).
- * @param[in] data_digest_size Length of optional data digest (0 or
- * 4 for now) to add.
* @return Pointer to allocated and zero filled PDU or NULL
* in case of an error (usually memory exhaustion).
*/
-static iscsi_bhs_packet *iscsi_connection_pdu_append(iscsi_pdu *pdu, const uint ahs_len, const int header_digest_size, const uint32_t ds_len, const int data_digest_size)
+static iscsi_bhs_packet *iscsi_connection_pdu_resize(iscsi_pdu *pdu, const uint ahs_len, const uint32_t ds_len)
{
- if ( (ahs_len > ISCSI_MAX_AHS_SIZE) || ((header_digest_size != 0) && (header_digest_size != ISCSI_DIGEST_SIZE)) || ((data_digest_size != 0) && data_digest_size != ISCSI_DIGEST_SIZE) || (ds_len > ISCSI_MAX_DS_SIZE) )
+ if ( (ahs_len > ISCSI_MAX_AHS_SIZE) || (ds_len > ISCSI_MAX_DS_SIZE) || (ahs_len % 4 != 0) ) {
+ logadd( LOG_ERROR, "iscsi_connection_pdu_resize: Invalid AHS or DataSegment packet size" );
return NULL;
+ }
- if ( (ahs_len != pdu->ahs_len) || (header_digest_size != pdu->header_digest_size) || (ds_len != pdu->ds_len) || (data_digest_size != pdu->data_digest_size) ) {
+ if ( (ahs_len != pdu->ahs_len) || (ds_len != pdu->ds_len) ) {
iscsi_bhs_packet *bhs_pkt;
const uint32_t pkt_ds_len = ISCSI_ALIGN(ds_len, ISCSI_ALIGN_SIZE);
- const uint32_t old_len = (uint32_t) (sizeof(struct iscsi_bhs_packet) + (uint32_t) pdu->ahs_len + pdu->header_digest_size + pdu->ds_len + ((pdu->ds_len != 0UL) ? (uint32_t) pdu->data_digest_size : 0UL));
- const uint32_t new_len = (uint32_t) (sizeof(struct iscsi_bhs_packet) + (uint32_t) ahs_len + header_digest_size + pkt_ds_len + ((pkt_ds_len != 0UL) ? (uint32_t) data_digest_size : 0UL));
+ const uint32_t old_len = (uint32_t) (sizeof(struct iscsi_bhs_packet) + (uint32_t) pdu->ahs_len + ISCSI_ALIGN(pdu->ds_len, ISCSI_ALIGN_SIZE));
+ const uint32_t new_len = (uint32_t) (sizeof(struct iscsi_bhs_packet) + (uint32_t) ahs_len + pkt_ds_len);
if ( new_len > old_len ) {
bhs_pkt = realloc( pdu->bhs_pkt, new_len );
if ( bhs_pkt == NULL ) {
- logadd( LOG_ERROR, "iscsi_connection_pdu_append: Out of memory while reallocating iSCSI PDU packet data" );
+ logadd( LOG_ERROR, "iscsi_connection_pdu_resize: Out of memory while reallocating iSCSI PDU packet data" );
return NULL;
}
@@ -3601,182 +2984,19 @@ static iscsi_bhs_packet *iscsi_connection_pdu_append(iscsi_pdu *pdu, const uint
bhs_pkt = pdu->bhs_pkt;
}
- pdu->ahs_pkt = (ahs_len != 0U) ? (iscsi_ahs_packet *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) ) : NULL;
- pdu->header_digest = (header_digest_size != 0) ? (iscsi_header_digest *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len) : NULL;
- pdu->ds_cmd_data = (pkt_ds_len != 0UL) ? (iscsi_scsi_ds_cmd_data *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len + header_digest_size) : NULL;
- pdu->data_digest = ((pkt_ds_len != 0UL) && (data_digest_size != 0)) ? (iscsi_data_digest *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len + header_digest_size + pkt_ds_len) : NULL;
+ pdu->ahs_pkt = (ahs_len != 0U) ? (iscsi_ahs_packet *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet)) : NULL;
+ pdu->ds_cmd_data = (pkt_ds_len != 0UL) ? (iscsi_scsi_ds_cmd_data *) (((uint8_t *) bhs_pkt) + sizeof(struct iscsi_bhs_packet) + ahs_len) : NULL;
pdu->ahs_len = ahs_len;
- pdu->header_digest_size = header_digest_size;
- pdu->ds_len = pkt_ds_len;
- pdu->len = pkt_ds_len;
- pdu->data_digest_size = data_digest_size;
+ pdu->ds_len = ds_len;
- if ( pkt_ds_len != 0UL )
+ if ( pkt_ds_len != 0UL ) {
memset( (((uint8_t *) pdu->ds_cmd_data) + ds_len), 0, (pkt_ds_len - ds_len) );
+ }
}
return pdu->bhs_pkt;
}
-/// CRC32C lookup table. Created with a polynomial reflect value of 0x82F63B78.
-static const uint32_t crc32c_lut[] = {
- 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
- 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
- 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
- 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
- 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
- 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
- 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
- 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
- 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
- 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
- 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
- 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
- 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
- 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
- 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
- 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
- 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
- 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
- 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
- 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
- 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
- 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
- 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
- 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
- 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
- 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
- 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
- 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
- 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
- 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
- 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
- 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351};
-
-/**
- * @brief Calculates digest (CRC32C).
- *
- * Calculates CRC32C with 0x82F63B78 polynomial
- * reflect according to iSCSI specs.\n
- * TODO: Implement optimized SSE4.2 and ARM versions
- *
- * @param[in] data Pointer to data to calculate CRC32C for.
- * @param[in] len Length of data to be calculated. Must be
- * divisable by 4 which is guaranteed by iSCSI standard.
- * @param[in] crc32c Previous CRC32C in case of multiple passes.
- * @return CRC32C value. THis function cannot fail.
- */
-static inline uint32_t iscsi_crc32c_update(const uint8_t *data, const uint len, uint32_t crc32c)
-{
- for ( uint i = 0; i < len - 3; i += 4 ) {
- crc32c = (crc32c >> 8UL) ^ crc32c_lut[(crc32c ^ data[i]) & 0xFF];
- crc32c = (crc32c >> 8UL) ^ crc32c_lut[(crc32c ^ data[i + 1]) & 0xFF];
- crc32c = (crc32c >> 8UL) ^ crc32c_lut[(crc32c ^ data[i + 2]) & 0xFF];
- crc32c = (crc32c >> 8UL) ^ crc32c_lut[(crc32c ^ data[i + 3]) & 0xFF];
- }
-
- return crc32c;
-}
-
-/**
- * @brief Calculate and store iSCSI header digest (CRC32C).
- *
- * Calculates header digest (CRC32C) with
- * 0x82F63B78 polynomial reflect according
- * to iSCSI specs and stores the result in
- * the iSCSI packet data. This function
- * cannot fail.
- *
- * @param[out] header_digest Pointer to iSCSI header digest
- * packet data to put CRC32C into.
- * May NOT be NULL, so be careful.
- * @param[in] packet_data Pointer to ISCSI BHS packet to
- * calculate CRC32C for. NULL is NOT
- * allowed here, take caution.
- * @param[in] ahs_len AHS segment length in bytes.
- */
-static void iscsi_connection_pdu_digest_header_update(iscsi_header_digest *header_digest, const iscsi_bhs_packet *packet_data, const uint ahs_len)
-{
- const uint32_t crc32c = iscsi_crc32c_update( (uint8_t *) packet_data, (sizeof(struct iscsi_bhs_packet) + ahs_len), ISCSI_CRC32C_INITIAL ) ^ ISCSI_CRC32C_XOR;
-
- iscsi_put_le32( (uint8_t *) &header_digest->crc32c, crc32c );
-}
-
-/**
- * @brief Validates a stored iSCSI header digest (CRC32C) with actual header data.
- *
- * Verifies header digest (CRC32C) with
- * 0x82F63B78 polynomial reflect according
- * to iSCSI specs. This function cannot
- * fail.
- *
- * @param[in] header_digest Pointer to iSCSI header digest
- * packet data to compare CRC32C with.
- * May NOT be NULL, so be careful.
- * @param[in] packet_data Pointer to ISCSI BHS packet to
- * validate CRC32C for. May NOT be NULL,
- * so be careful.
- * @param[in] ahs_len AHS segment length in bytes.
- * @retval true CRC32C matches the stored value.
- * @retval false CRC32C does NOT match the stored value.
- */
-static bool iscsi_connection_pdu_digest_header_verify(const iscsi_header_digest *header_digest, const iscsi_bhs_packet *packet_data, const uint ahs_len)
-{
- const uint32_t crc32c = iscsi_crc32c_update( (uint8_t *) packet_data, (sizeof(struct iscsi_bhs_packet) + ahs_len), ISCSI_CRC32C_INITIAL ) ^ ISCSI_CRC32C_XOR;
-
- return (iscsi_get_le32(crc32c) == header_digest->crc32c);
-}
-
-/**
- * @brief Calculate iSCSI data digest (CRC32C).
- *
- * Calculates data digest (CRC32) with
- * 0x82F63B78 polynomial reflect of a
- * whole DataSegment (CRC32C) according
- * to the iSCSI specs.\n
- * The resulting CRC32C will be stored
- * in the iSCSI packet.
- *
- * @param[out] data_digest Pointer to iSCSI data digest
- * packet data to put CRC32C into.
- * May NOT be NULL, so be careful.
- * @param[in] ds_cmd_data Pointer to iSCSI DataSegment packet to
- * calculate CRC32C for. NULL is NOT
- * allowed here, take caution.
- * @param[in] ds_len Data segment length in bytes.
- */
-static void iscsi_connection_pdu_digest_data_update(iscsi_data_digest *data_digest, const iscsi_scsi_ds_cmd_data *ds_cmd_data, const uint32_t ds_len)
-{
- const uint32_t crc32c = iscsi_crc32c_update( (uint8_t *) ds_cmd_data, ISCSI_ALIGN(ds_len, ISCSI_DIGEST_SIZE), ISCSI_CRC32C_INITIAL ) ^ ISCSI_CRC32C_XOR;
-
- iscsi_put_le32( (uint8_t *) &data_digest->crc32c, crc32c );
-}
-
-/**
- * @brief Validates a stored iSCSI data digest (CRC32C) with actual DataSegment.
- *
- * Verifies data digest (CRC32C) with
- * 0x82F63B78 polynomial reflect according
- * to iSCSI specs. This function cannot
- * fail.
- *
- * @param[out] data_digest Pointer to iSCSI data digest
- * packet data to compare CRC32C with.
- * May NOT be NULL, so be careful.
- * @param[in] ds_cmd_data Pointer to iSCSI DataSegment
- * packet to calculate CRC32C for. May NOT
- * be NULL, so be careful.
- * @param[in] ds_len Data segment length in bytes.
- * @retval true CRC32C matches the stored value.
- * @retval false CRC32C does NOT match the stored value.
- */
-static bool iscsi_connection_pdu_digest_data_verify(const iscsi_data_digest *data_digest, const iscsi_scsi_ds_cmd_data *ds_cmd_data, const uint32_t ds_len)
-{
- const uint32_t crc32c = iscsi_crc32c_update( (uint8_t *) ds_cmd_data, ISCSI_ALIGN(ds_len, ISCSI_DIGEST_SIZE), ISCSI_CRC32C_INITIAL ) ^ ISCSI_CRC32C_XOR;
-
- return (iscsi_get_le32(crc32c) == data_digest->crc32c);
-}
-
/**
* @brief Writes and sends a response PDU to the client.
*
@@ -3793,27 +3013,23 @@ static bool iscsi_connection_pdu_digest_data_verify(const iscsi_data_digest *dat
*/
static bool iscsi_connection_pdu_write(iscsi_connection *conn, iscsi_pdu *pdu)
{
- if ( ISCSI_GET_OPCODE(pdu->bhs_pkt->opcode) != ISCSI_OPCODE_CLIENT_LOGIN_REQ ) {
- if ( pdu->header_digest != NULL )
- iscsi_connection_pdu_digest_header_update( pdu->header_digest, pdu->bhs_pkt, pdu->ahs_len );
-
- if ( pdu->data_digest != NULL )
- iscsi_connection_pdu_digest_data_update( pdu->data_digest, pdu->ds_cmd_data, pdu->ds_len );
- }
-
if ( conn->state >= ISCSI_CONNECT_STATE_EXITING ) {
iscsi_connection_pdu_destroy( pdu );
return false;
}
- const uint len = (uint) (sizeof(struct iscsi_bhs_packet) + pdu->ahs_len + conn->header_digest + ISCSI_ALIGN(pdu->ds_len, ISCSI_ALIGN_SIZE) + conn->data_digest);
+ // During allocation we already round up to ISCSI_ALIGN_SIZE, but store the requested size in the ds_len
+ // member, so it's safe to round up here before sending, the accessed memory will be valid and zeroed
+ const size_t len = (sizeof(struct iscsi_bhs_packet) + pdu->ahs_len + ISCSI_ALIGN(pdu->ds_len, ISCSI_ALIGN_SIZE));
+ const ssize_t rc = sock_sendAll( conn->client->sock, pdu->bhs_pkt, len, ISCSI_CONNECT_SOCKET_WRITE_RETRIES );
- bool ok = iscsi_connection_write( conn, (uint8_t *) pdu->bhs_pkt, len ) > 0;
iscsi_connection_pdu_destroy( pdu );
- if (!ok) {
+
+ if ( rc != (ssize_t)len ) {
conn->state = ISCSI_CONNECT_STATE_EXITING;
+ return false;
}
- return ok;
+ return true;
}
/**
@@ -3874,7 +3090,7 @@ static int iscsi_connection_handle_reject(iscsi_connection *conn, iscsi_pdu *pdu
pdu->flags |= ISCSI_PDU_FLAGS_REJECTED;
const uint32_t ds_len = (uint32_t) sizeof(struct iscsi_bhs_packet) + ((uint32_t) pdu->bhs_pkt->total_ahs_len << 2UL);
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, ds_len, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, ds_len );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_handle_reject: Out of memory while allocating iSCSI reject response PDU" );
@@ -3990,7 +3206,7 @@ static int iscsi_connection_pdu_header_handle_login_req(iscsi_connection *conn,
if ( pdu->ds_len > ISCSI_DEFAULT_RECV_DS_LEN )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
- iscsi_pdu *login_response_pdu = iscsi_connection_pdu_create( conn, 0U, 0, ISCSI_DEFAULT_RECV_DS_LEN, 0 );
+ iscsi_pdu *login_response_pdu = iscsi_connection_pdu_create( conn, 8192 );
if ( login_response_pdu == NULL )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
@@ -4097,11 +3313,10 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
task->scsi_task.flags |= ISCSI_SCSI_TASK_FLAGS_XFER_READ;
if ( (scsi_cmd_pkt->flags_task & ISCSI_SCSI_CMD_FLAGS_TASK_WRITE) != 0 ) {
- return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
+ return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_COMMAND_NOT_SUPPORTED );
}
pdu->task = task;
- pdu->task_ref_cnt++;
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -4123,8 +3338,7 @@ static int iscsi_connection_pdu_header_handle_scsi_cmd(iscsi_connection *conn, i
*/
static int iscsi_connection_pdu_header_handle_text_req(iscsi_connection *conn, iscsi_pdu *pdu)
{
- if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_MAX_AHS_SIZE + conn->header_digest
- + ISCSI_SESSION_DEFAULT_FIRST_BURST_LEN + conn->data_digest) )
+ if ( pdu->ds_len > (uint) (sizeof(struct iscsi_bhs_packet) + ISCSI_DEFAULT_RECV_DS_LEN) )
return iscsi_connection_handle_reject( conn, pdu, ISCSI_REJECT_REASON_PROTOCOL_ERR );
iscsi_text_req_packet *text_req_pkt = (iscsi_text_req_packet *) pdu->bhs_pkt;
@@ -4169,7 +3383,7 @@ static int iscsi_connection_pdu_header_handle_logout_req(iscsi_connection *conn,
if ( (conn->session != NULL) && (conn->session->type == ISCSI_SESSION_TYPE_DISCOVERY) && (logout_req_pkt->reason_code != ISCSI_LOGOUT_REQ_REASON_CODE_CLOSE_SESSION) )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, 0UL, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0UL );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_pdu_header_handle_logout_req: Out of memory while allocating iSCSI logout response PDU" );
@@ -4245,7 +3459,7 @@ static int iscsi_connection_pdu_header_handle(iscsi_connection *conn, iscsi_pdu
return iscsi_connection_pdu_header_handle_login_req( conn, pdu );
if ( ((conn->flags & ISCSI_CONNECT_FLAGS_FULL_FEATURE) == 0) && (conn->state == ISCSI_CONNECT_STATE_RUNNING) ) {
- iscsi_pdu *login_response_pdu = iscsi_connection_pdu_create( conn, 0U, 0, 0UL, 0 );
+ iscsi_pdu *login_response_pdu = iscsi_connection_pdu_create( conn, 0UL );
if ( login_response_pdu == NULL )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
@@ -4326,7 +3540,7 @@ static int iscsi_connection_pdu_data_handle_nop_out(iscsi_connection *conn, iscs
if ( init_task_tag == 0xFFFFFFFFUL )
return ISCSI_CONNECT_PDU_READ_OK;
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, ds_len, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, ds_len );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_pdu_data_handle_nop_out: Out of memory while allocating iSCSI NOP-In response PDU" );
@@ -4401,34 +3615,6 @@ static int iscsi_connection_pdu_data_handle_scsi_cmd(iscsi_connection *conn, isc
return ISCSI_CONNECT_PDU_READ_OK;
}
-/**
- * @brief Determines iSCSI session login steps for normal authentication.
- *
- * This function also does related validation checks.
- *
- * @param[in] conn Pointer to iSCSI connection, may NOT be
- * NULL, so take caution.
- * @param[in] login_response_pdu Pointer to login response PDU where
- * NULL is not allowed, so be careful.
- * @param[in] target_name Pointer to hash map containing the login
- * request key and value pairs and may NOT be NULL, so
- * take caution.
- * @return 0 on successful operation, a negative error code
- * otherwise.
- */
-static int iscsi_connection_login_session_normal(iscsi_connection *conn, iscsi_pdu *login_response_pdu, const char *target_name)
-{
- int rc = iscsi_connection_login_check_target( conn, login_response_pdu, target_name );
-
- if ( rc != 0 )
- return rc;
-
- conn->flags &= ~(ISCSI_CONNECT_FLAGS_CHAP_REQUIRE | ISCSI_CONNECT_FLAGS_CHAP_MUTUAL);
- conn->flags |= ISCSI_CONNECT_FLAGS_CHAP_DISABLE;
-
- return rc;
-}
-
/*
* This function is used to set the info in the connection data structure
* return
@@ -4470,23 +3656,23 @@ static int iscsi_connection_login_set_info(iscsi_connection *conn, iscsi_pdu *lo
* may NOT be NULL, so be careful.
* @param[in] login_response_pdu Pointer to login response PDU.
* NULL is not allowed here, so take caution.
- * @param[in] key_value_pairs Pointer to key and value pairs.
+ * @param[in] kvpairs Pointer to key and value pairs.
* which may NOT be NULL, so take caution.
* @param[in] cid Connection ID (CID).
* @return 0 on success, a negative error code otherwise.
*/
-static int iscsi_connection_handle_login_phase_none(iscsi_connection *conn, iscsi_pdu *login_response_pdu, iscsi_login_kvp *key_value_pairs, uint cid)
+static int iscsi_connection_handle_login_phase_none(iscsi_connection *conn, iscsi_pdu *login_response_pdu, iscsi_negotiation_kvp *kvpairs, uint cid)
{
int type, rc;
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- rc = iscsi_login_check_session_type( login_response_pdu, key_value_pairs->AuthMethod );
+ rc = iscsi_login_parse_session_type( login_response_pdu, kvpairs->SessionType, &type );
if ( rc < 0 )
return rc;
- if ( type == ISCSI_SESSION_TYPE_NORMAL ) {
- rc = iscsi_connection_login_session_normal( conn, login_response_pdu, key_value_pairs );
+ if ( kvpairs->TargetName != NULL && type == ISCSI_SESSION_TYPE_NORMAL ) {
+ rc = iscsi_image_from_target( conn, login_response_pdu, kvpairs->TargetName );
} else {
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISSING_PARAMETER;
@@ -4500,120 +3686,105 @@ static int iscsi_connection_handle_login_phase_none(iscsi_connection *conn, iscs
return iscsi_connection_login_set_info( conn, login_response_pdu, type, cid );
}
+static int iscsi_write_login_options_to_pdu( iscsi_connection *conn, iscsi_negotiation_kvp *pairs, iscsi_pdu *response_pdu )
+{
+ uint payload_len = response_pdu->ds_write_pos;
+
+# define ADD_KV_INTERNAL(num, key, value) do { \
+int rc = iscsi_append_key_value_pair_packet( num, key, value, (char *)response_pdu->ds_cmd_data, payload_len, response_pdu->ds_len ); \
+if ( rc < 0 ) return -1; \
+payload_len += rc; \
+} while (0)
+# define ADD_KV_OPTION_INT(key) do { \
+if ( pairs->key != -1 ) ADD_KV_INTERNAL( true, #key, (const char *)(size_t)conn->session->opts.key ); \
+} while (0)
+# define ADD_KV_OPTION_STR(key) do { \
+if ( pairs->key != NULL ) ADD_KV_INTERNAL( false, #key, conn->session->opts.key ); \
+} while (0)
+# define ADD_KV_PLAIN_INT(key, value) do { \
+if ( pairs->key != -1 ) ADD_KV_INTERNAL( true, #key, (const char *)(size_t)(value) ); \
+} while (0)
+# define ADD_KV_PLAIN_STR(key, value) do { \
+if ( pairs->key != NULL ) ADD_KV_INTERNAL( false, #key, value ); \
+} while (0)
+ ADD_KV_OPTION_INT( MaxRecvDataSegmentLength );
+ ADD_KV_OPTION_INT( MaxBurstLength );
+ ADD_KV_OPTION_INT( FirstBurstLength );
+ ADD_KV_PLAIN_INT( MaxConnections, 1 );
+ ADD_KV_PLAIN_INT( ErrorRecoveryLevel, 0 );
+ ADD_KV_PLAIN_STR( HeaderDigest, "None" );
+ ADD_KV_PLAIN_STR( DataDigest, "None" );
+# undef ADD_KV_PLAIN
+# undef ADD_KV_OPTION_INT
+# undef ADD_KV_OPTION_STR
+
+ if ( payload_len <= response_pdu->ds_len ) {
+ response_pdu->ds_write_pos = payload_len;
+ } else {
+ response_pdu->ds_write_pos = response_pdu->ds_len;
+ }
+ return (int)payload_len;
+}
+
/**
- * @brief Handles the Current Stage (CSG) bit of login response.
+ * @brief Handles iSCSI connection login response.
*
- * This function determines the authentication method
- * and processes the various authentication stages.
+ * This function negotiates the login parameters
+ * and determines the authentication method.
*
- * @param[in] conn Pointer to iSCSI connection, may NOT be
- * NULL, so take caution.
+ * @param[in] conn Pointer to iSCSI connection,
+ * may NOT be NULL, so be careful.
* @param[in] login_response_pdu Pointer to login response PDU.
- * NULL is NOT an allowed value here, so be careful.
- * @param[in] auth_method auth method requested, or NULL if not specified
- * @return 0 if authentication has been handled successfully,
- * a negative error code otherwise.
+ * NULL is not allowed here, so take caution.
+ * @return 0 on success, a negative error code otherwise.
*/
-static int iscsi_connecction_handle_login_response_csg_bit(iscsi_connection *conn, iscsi_pdu *login_response_pdu, char *auth_method)
+static int iscsi_connecction_handle_login_response(iscsi_connection *conn, iscsi_pdu *login_response_pdu, iscsi_negotiation_kvp *pairs)
{
iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
+ iscsi_connection_update_key_value_pairs( conn, pairs );
+ int payload_len = iscsi_write_login_options_to_pdu( conn, pairs, login_response_pdu );
- switch ( ISCSI_LOGIN_RESPONSE_FLAGS_GET_CURRENT_STAGE(login_response_pkt->flags) ) {
- case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_SECURITY_NEGOTIATION : {
- if ( auth_method != NULL && strcasecmp( auth_method, "None" ) == 0 ) {
- conn->flags |= ISCSI_CONNECT_FLAGS_AUTH;
- } else {
- login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
-
- return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
- }
-
- break;
- }
- case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION : {
- if ( conn->state == ISCSI_CONNECT_STATE_INVALID ) {
- if ( conn->flags & ISCSI_CONNECT_FLAGS_CHAP_REQUIRE ) {
- login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
-
- return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
- } else {
- conn->flags |= ISCSI_CONNECT_FLAGS_AUTH;
- }
- }
-
- if ( (conn->flags & ISCSI_CONNECT_FLAGS_AUTH) == 0 ) {
- login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
+ if ( payload_len < 0 || payload_len > login_response_pdu->ds_len ) {
+ login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_SERVER_ERR;
+ login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_OUT_OF_RESOURCES;
- return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
- }
+ return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
+ }
- break;
- }
- case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_FULL_FEATURE_PHASE :
- default : {
+ // Handle current stage (CSG bits)
+ switch ( ISCSI_LOGIN_RESPONSE_FLAGS_GET_CURRENT_STAGE(login_response_pkt->flags) ) {
+ case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_SECURITY_NEGOTIATION : {
+ if ( pairs->AuthMethod != NULL && strcasecmp( pairs->AuthMethod, "None" ) == 0 ) {
+ conn->flags |= ISCSI_CONNECT_FLAGS_AUTH;
+ } else {
+ // Only "None" supported
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC;
+ login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
-
- break;
}
- }
- return ISCSI_CONNECT_PDU_READ_OK;
-}
-
-/**
- *
- * @brief Checks whether the session type is valid.
- *
- * This function also can be used to output
- * debugging info about the session, which
- * is currently not implemented.
- *
- * @param[in] conn Pointer to iSCSI connection to be checked for
- * validity. May NOT be NULL, so be careful.
- * @param[in] login_response_pdu Pointer to login response PDU to
- * set status class and detail in case of an error.
- * NULL is not an allowed value here, take caution.
- * @return 0 if the session type is valid, a negative error code
- * otherwise.
- */
-static int iscsi_connection_login_session_info_notify(iscsi_connection *conn, iscsi_pdu *login_response_pdu)
-{
- if ( (conn->session->type != ISCSI_SESSION_TYPE_NORMAL) && (conn->session->type != ISCSI_SESSION_TYPE_DISCOVERY) ) {
- iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
+ break;
+ }
+ case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_LOGIN_OPERATIONAL_NEGOTIATION : {
+ if ( conn->state == ISCSI_CONNECT_STATE_INVALID ) {
+ conn->flags |= ISCSI_CONNECT_FLAGS_AUTH;
+ }
+ break;
+ }
+ case ISCSI_LOGIN_RESPONSE_FLAGS_CURRENT_STAGE_FULL_FEATURE_PHASE :
+ default : {
login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC;
return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
}
+ }
- return ISCSI_CONNECT_PDU_READ_OK;
-}
-
-/**
- * @brief Handles the Transit (T) bit of login response.
- *
- * This function handles the transitional stages
- * of the authentication process.
- *
- * @param[in] conn Pointer to iSCSI connection, may NOT be
- * NULL, so take caution.
- * @param[in] login_response_pdu Pointer to login response PDU.
- * NULL is NOT an allowed value here, so be careful.
- * @return 0 if transition has been handled successfully,
- * a negative error code otherwise.
- */
-static int iscsi_connecction_handle_login_response_t_bit(iscsi_connection *conn, iscsi_pdu *login_response_pdu)
-{
- iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
-
- switch ( ISCSI_LOGIN_RESPONSE_FLAGS_GET_NEXT_STAGE(login_response_pkt->flags) ) {
+ if ( (login_response_pkt->flags & ISCSI_LOGIN_RESPONSE_FLAGS_TRANSIT) != 0 ) {
+ // Client set the transition bit - requests to move on to next stage
+ switch ( ISCSI_LOGIN_RESPONSE_FLAGS_GET_NEXT_STAGE(login_response_pkt->flags) ) {
case ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_SECURITY_NEGOTIATION : {
conn->login_phase = ISCSI_LOGIN_RESPONSE_FLAGS_NEXT_STAGE_SECURITY_NEGOTIATION;
@@ -4629,10 +3800,15 @@ static int iscsi_connecction_handle_login_response_t_bit(iscsi_connection *conn,
iscsi_put_be16( (uint8_t *) &login_response_pkt->tsih, (uint16_t) conn->session->tsih );
- const int rc = iscsi_connection_login_session_info_notify( conn, login_response_pdu );
+ if ( (conn->session->type != ISCSI_SESSION_TYPE_NORMAL) && (conn->session->type != ISCSI_SESSION_TYPE_DISCOVERY) ) {
+ logadd( LOG_DEBUG1, "Unsupported session type %d, rejecting", conn->session->type );
+ iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
- if ( rc < 0 )
- return rc;
+ login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
+ login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC;
+
+ return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
+ }
conn->flags |= ISCSI_CONNECT_FLAGS_FULL_FEATURE;
@@ -4643,8 +3819,7 @@ static int iscsi_connecction_handle_login_response_t_bit(iscsi_connection *conn,
login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_MISC;
return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
-
- break;
+ }
}
}
@@ -4652,48 +3827,6 @@ static int iscsi_connecction_handle_login_response_t_bit(iscsi_connection *conn,
}
/**
- * @brief Handles iSCSI connection login response.
- *
- * This function negotiates the login parameters
- * and determines the authentication method.
- *
- * @param[in] conn Pointer to iSCSI connection,
- * may NOT be NULL, so be careful.
- * @param[in] login_response_pdu Pointer to login response PDU.
- * NULL is not allowed here, so take caution.
- * @param[in] key_value_pairs Pointer to key and value pairs.
- * which may NOT be NULL, so take caution.
- * @return 0 on success, a negative error code otherwise.
- */
-static int iscsi_connecction_handle_login_response(iscsi_connection *conn, iscsi_pdu *login_response_pdu, iscsi_login_kvp *key_value_pairs)
-{
- iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
-
-
- // TODO: Handle KVPs
- int ds_len = -1;
-
- if ( ds_len < 0L ) {
- login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
- login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
-
- return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
- }
-
- login_response_pdu->ds_len = (uint32_t) ds_len;
-
- int rc = iscsi_connecction_handle_login_response_csg_bit( conn, login_response_pdu, key_value_pairs->AuthMethod );
-
- if ( rc < 0 )
- return rc;
-
- if ( (login_response_pkt->flags & ISCSI_LOGIN_RESPONSE_FLAGS_TRANSIT) != 0 )
- rc = iscsi_connecction_handle_login_response_t_bit( conn, login_response_pdu );
-
- return rc;
-}
-
-/**
* @brief Handles an incoming iSCSI payload data login request PDU.
*
* This function handles login request payload
@@ -4710,6 +3843,7 @@ static int iscsi_connecction_handle_login_response(iscsi_connection *conn, iscsi
*/
static int iscsi_connection_pdu_data_handle_login_req(iscsi_connection *conn, iscsi_pdu *pdu)
{
+ int rc;
iscsi_pdu *login_response_pdu = (iscsi_pdu *) conn->login_response_pdu;
if ( login_response_pdu == NULL )
@@ -4717,16 +3851,20 @@ static int iscsi_connection_pdu_data_handle_login_req(iscsi_connection *conn, is
iscsi_login_req_packet *login_req_pkt = (iscsi_login_req_packet *) pdu->bhs_pkt;
uint cid = iscsi_get_be16(login_req_pkt->cid);
- int rc = iscsi_connection_save_incoming_key_value_pairs( conn, NULL, login_response_pdu, pdu );
- if ( rc < 0 ) {
- iscsi_connection_pdu_login_response( conn, login_response_pdu );
+ iscsi_negotiation_kvp pairs;
+ iscsi_login_response_packet *login_response_pkt = (iscsi_login_response_packet *) login_response_pdu->bhs_pkt;
+ rc = iscsi_parse_login_key_value_pairs( &pairs, (uint8_t *) pdu->ds_cmd_data, pdu->ds_len );
- return ISCSI_CONNECT_PDU_READ_OK;
+ if ( rc < 0 || rc > login_response_pdu->ds_len ) {
+ login_response_pkt->status_class = ISCSI_LOGIN_RESPONSE_STATUS_CLASS_CLIENT_ERR;
+ login_response_pkt->status_detail = ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_CLIENT_ERR_AUTH_ERR;
+
+ return ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE;
}
if ( conn->state == ISCSI_CONNECT_STATE_INVALID ) {
- rc = iscsi_connection_handle_login_phase_none( conn, login_response_pdu, NULL, cid );
+ rc = iscsi_connection_handle_login_phase_none( conn, login_response_pdu, &pairs, cid );
if ( (rc == ISCSI_CONNECT_PDU_READ_ERR_LOGIN_RESPONSE) || (rc == ISCSI_CONNECT_PDU_READ_ERR_LOGIN_PARAMETER) ) {
iscsi_connection_pdu_login_response( conn, login_response_pdu );
@@ -4735,7 +3873,7 @@ static int iscsi_connection_pdu_data_handle_login_req(iscsi_connection *conn, is
}
}
- rc = iscsi_connecction_handle_login_response( conn, login_response_pdu, NULL );
+ rc = iscsi_connecction_handle_login_response( conn, login_response_pdu, &pairs );
if ( rc == ISCSI_CONNECT_PDU_READ_OK ) {
conn->state = ISCSI_CONNECT_STATE_RUNNING;
@@ -4764,14 +3902,14 @@ static int iscsi_connection_pdu_data_handle_login_req(iscsi_connection *conn, is
static int iscsi_connection_pdu_data_handle_text_req(iscsi_connection *conn, iscsi_pdu *pdu)
{
iscsi_text_req_packet *text_req_pkt = (iscsi_text_req_packet *) pdu->bhs_pkt;
- int rc = iscsi_parse_login_key_value_pairs( NULL, (uint8_t *) pdu->ds_cmd_data, pdu->ds_len, ((text_req_pkt->flags & ISCSI_TEXT_REQ_FLAGS_CONTINUE) != 0), &conn->text_partial_pairs );
+ iscsi_negotiation_kvp pairs;
+ int rc = iscsi_parse_login_key_value_pairs( &pairs, (uint8_t *) pdu->ds_cmd_data, pdu->ds_len );
if ( rc < 0 ) {
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
- iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 0U, conn->header_digest,
- conn->session->opts.MaxRecvDataSegmentLength, conn->data_digest );
+ iscsi_pdu *response_pdu = iscsi_connection_pdu_create( conn, 8192 );
if ( response_pdu == NULL ) {
logadd( LOG_ERROR, "iscsi_connection_pdu_data_handle_text_req: Out of memory while allocating iSCSI text response PDU" );
@@ -4779,33 +3917,24 @@ static int iscsi_connection_pdu_data_handle_text_req(iscsi_connection *conn, isc
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
- response_pdu->ds_len = 0UL;
+ iscsi_connection_update_key_value_pairs( conn, &pairs );
- // TODO: Write stuff to reply packet
- int ds_len = -1;
+ int payload_len = iscsi_write_login_options_to_pdu( conn, &pairs, response_pdu );
- if ( ds_len < 0L ) {
+ if ( payload_len < 0 || payload_len > response_pdu->ds_len ) {
iscsi_connection_pdu_destroy( response_pdu );
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
- iscsi_text_response_packet *text_response_pkt = (iscsi_text_response_packet *) response_pdu->bhs_pkt;
+ iscsi_text_response_packet *text_response_pkt = (iscsi_text_response_packet *) iscsi_connection_pdu_resize( response_pdu, 0, response_pdu->ds_write_pos );
text_response_pkt->opcode = ISCSI_OPCODE_SERVER_TEXT_RES;
- text_response_pkt->flags = 0;
-
- if ( (text_req_pkt->flags & ISCSI_TEXT_REQ_FLAGS_CONTINUE) != 0 )
- text_response_pkt->flags |= (int8_t) ISCSI_TEXT_RESPONSE_FLAGS_CONTINUE;
-
- if ( (text_req_pkt->flags & ISCSI_TEXT_REQ_FLAGS_FINAL) != 0 )
- text_response_pkt->flags |= (int8_t) ISCSI_TEXT_RESPONSE_FLAGS_FINAL;
+ text_response_pkt->flags = (int8_t) ISCSI_TEXT_RESPONSE_FLAGS_FINAL;
- text_response_pkt->reserved = 0U;
+ text_response_pkt->reserved = 0;
- text_response_pkt = (iscsi_text_response_packet *) iscsi_connection_pdu_append( response_pdu, response_pdu->ahs_len, conn->header_digest, ds_len, conn->data_digest );
-
- iscsi_put_be32( (uint8_t *) &text_response_pkt->total_ahs_len, ds_len ); // TotalAHSLength is always 0 and DataSegmentLength is 24-bit, so write in one step.
+ iscsi_put_be32( (uint8_t *) &text_response_pkt->total_ahs_len, payload_len ); // TotalAHSLength is always 0 and DataSegmentLength is 24-bit, so write in one step.
text_response_pkt->lun = text_req_pkt->lun; // Copying over doesn't change endianess.
text_response_pkt->init_task_tag = text_req_pkt->init_task_tag; // Copying over doesn't change endianess.
@@ -4828,7 +3957,6 @@ static int iscsi_connection_pdu_data_handle_text_req(iscsi_connection *conn, isc
text_response_pkt->reserved2[1] = 0ULL;
iscsi_connection_pdu_write( conn, response_pdu );
- iscsi_connection_update_key_value_pairs( conn );
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -4897,12 +4025,14 @@ static int iscsi_connection_pdu_data_handle(iscsi_connection *conn, iscsi_pdu *p
* @brief Retrieves and merges splitted iSCSI PDU data read from TCP/IP socket.
*
* This function handles partial reads of data
- * packet.\n
- * Since iSCSI data can span multiple packets, not
- * only by TCP/IP itself, but also by iSCSI protocol
- * specifications, multiple calls are needed in order
- * to be sure that all data packets have been
- * received.
+ * packets.\n
+ * The function is guaranteed to read as many bytes as indicated by the
+ * PDU struct, unless the read timeout is reached, or the connection
+ * is closed/reset.\n
+ * Care is also taken for padding bytes that have to be read. It is
+ * assumed the according buffer will have enough space for the padding
+ * bytes, which is always guaranteed when using the create and resize
+ * helpers for allocating PDUs.
*
* @param[in] conn Pointer to iSCSI connection to read TCP/IP data from.
* @param[in] pdu Pointer to iSCSI PDU to read TCP/IP data into.
@@ -4912,36 +4042,19 @@ static int iscsi_connection_pdu_data_handle(iscsi_connection *conn, iscsi_pdu *p
*/
static int iscsi_connection_pdu_data_read(iscsi_connection *conn, iscsi_pdu *pdu)
{
- const uint32_t ds_len = pdu->ds_len;
+ const uint32_t ds_len = ISCSI_ALIGN( pdu->ds_len, ISCSI_ALIGN_SIZE );
- if ( pdu->pos < ds_len ) {
- const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->ds_cmd_data) + pdu->pos), (ds_len - pdu->pos) );
+ if ( pdu->recv_pos < ds_len ) {
+ const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->ds_cmd_data) + pdu->recv_pos), (ds_len - pdu->recv_pos) );
if ( len < 0L )
return len;
- pdu->pos += len;
+ pdu->recv_pos += len;
}
- if ( pdu->pos < ds_len )
- return ISCSI_CONNECT_PDU_READ_PROCESSED;
-
- if ( pdu->data_digest != NULL ) {
- if ( (int) pdu->data_digest_pos < pdu->data_digest_size ) {
- const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->data_digest) + pdu->data_digest_pos), (pdu->data_digest_size - pdu->data_digest_pos) );
-
- if ( len < 0L )
- return len;
-
- pdu->data_digest_pos += len;
-
- if ( (int) pdu->data_digest_pos < pdu->data_digest_size )
- return ISCSI_CONNECT_PDU_READ_OK;
- }
-
- if ( !iscsi_connection_pdu_digest_data_verify( pdu->data_digest, pdu->ds_cmd_data, ds_len ) )
- return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- }
+ if ( pdu->recv_pos < ds_len )
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -4974,7 +4087,7 @@ static int iscsi_connection_pdu_read(iscsi_connection *conn)
switch ( conn->pdu_recv_state ) {
case ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_READY : {
assert( conn->pdu_processing == NULL );
- conn->pdu_processing = iscsi_connection_pdu_create( conn, 0U, conn->header_digest, 0UL, conn->data_digest );
+ conn->pdu_processing = iscsi_connection_pdu_create( conn, 0UL );
if ( conn->pdu_processing == NULL )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
@@ -4984,75 +4097,47 @@ static int iscsi_connection_pdu_read(iscsi_connection *conn)
break;
}
case ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_HDR : {
- if ( pdu->bhs_pos < sizeof(struct iscsi_bhs_packet) ) {
+ while ( pdu->bhs_pos < sizeof(struct iscsi_bhs_packet) ) {
const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->bhs_pkt) + pdu->bhs_pos), (sizeof(struct iscsi_bhs_packet) - pdu->bhs_pos) );
if ( len < 0L ) {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
- break;
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
pdu->bhs_pos += len;
-
- if ( pdu->bhs_pos < sizeof(struct iscsi_bhs_packet) )
- return ISCSI_CONNECT_PDU_READ_OK;
}
if ( (conn->flags & ISCSI_CONNECT_FLAGS_LOGGED_OUT) != 0 ) {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
- break;
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
iscsi_bhs_packet *bhs_pkt = pdu->bhs_pkt;
- const uint ahs_len = ((uint) bhs_pkt->total_ahs_len << 2U);
+ const uint ahs_len = ((uint) bhs_pkt->total_ahs_len * 4);
const uint32_t ds_len = iscsi_get_be24(bhs_pkt->ds_len);
- bhs_pkt = iscsi_connection_pdu_append( pdu, ahs_len, conn->header_digest, ds_len, conn->data_digest );
+ bhs_pkt = iscsi_connection_pdu_resize( pdu, ahs_len, ds_len );
if ( bhs_pkt == NULL )
return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
- if ( pdu->ahs_pos < ahs_len ) {
- const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->ahs_pkt) + pdu->ahs_pos), (ahs_len - pdu->ahs_pos) );
+ int pos = 0;
+ while ( pos < ahs_len ) {
+ const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->ahs_pkt) + pos), (ahs_len - pos) );
if ( len < 0L ) {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
- break;
- }
-
- pdu->ahs_pos += len;
-
- if ( pdu->ahs_pos < ahs_len )
- return ISCSI_CONNECT_PDU_READ_OK;
- }
-
- if ( pdu->header_digest != NULL ) {
- if ( (int) pdu->header_digest_pos < pdu->header_digest_size ) {
- const int32_t len = iscsi_connection_read( conn, (((uint8_t *) pdu->header_digest) + pdu->header_digest_pos), (pdu->header_digest_size - pdu->header_digest_pos) );
-
- if ( len < 0L ) {
- conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
-
- break;
- }
-
- pdu->header_digest_pos += len;
-
- if ( (int) pdu->header_digest_pos < pdu->header_digest_size )
- return ISCSI_CONNECT_PDU_READ_OK;
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
}
- if ( !iscsi_connection_pdu_digest_header_verify( pdu->header_digest, bhs_pkt, ahs_len ) ) {
- conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
-
- break;
- }
+ pos += len;
}
- if ((iscsi_connection_pdu_header_handle( conn, pdu ) < 0)) {
+ if ( iscsi_connection_pdu_header_handle( conn, pdu ) < 0 ) {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
} else {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_DATA;
@@ -5067,7 +4152,7 @@ static int iscsi_connection_pdu_read(iscsi_connection *conn)
if ( len < 0 ) {
conn->pdu_recv_state = ISCSI_CONNECT_PDU_RECV_STATE_ERR;
- break;
+ return ISCSI_CONNECT_PDU_READ_ERR_FATAL;
} else if ( len > 0 ) {
return ISCSI_CONNECT_PDU_READ_OK;
}
@@ -5138,7 +4223,7 @@ void iscsi_connection_handle(dnbd3_client_t *client, const dnbd3_request_t *requ
return;
}
- conn->pdu_processing = iscsi_connection_pdu_create( conn, 0U, 0, 0UL, 0 );
+ conn->pdu_processing = iscsi_connection_pdu_create( conn, 0UL );
if ( conn->pdu_processing == NULL ) {
iscsi_connection_destroy( conn );