From 2b2529d1961b7ed5e77365f35ca40d3a161c3b67 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 11 Sep 2025 19:39:43 +0000 Subject: [PATCH 1/2] fix: check scsi_datain_unmarshall for NULL Signed-off-by: Peter Lieven --- lib/connect.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/connect.c b/lib/connect.c index 0b762fc..e35e5a4 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -101,15 +101,20 @@ iscsi_inquiry_page_0x80_cb(struct iscsi_context *iscsi, int status, if (!status) { inq = scsi_datain_unmarshall(task); - if (!iscsi->unit_serial_number[0]) { - ISCSI_LOG(iscsi, 2, "unit serial number is [%s]", inq->usn); - strncpy(iscsi->unit_serial_number, inq->usn, MAX_STRING_SIZE); - } else if (strncmp(iscsi->unit_serial_number, inq->usn, MAX_STRING_SIZE)) { - iscsi_set_error(iscsi, "unit serial number mismatch. got [%s] expected [%s]", - inq->usn, iscsi->unit_serial_number); - status = 1; + if (inq != NULL) { + if (!iscsi->unit_serial_number[0]) { + ISCSI_LOG(iscsi, 2, "unit serial number is [%s]", inq->usn); + strncpy(iscsi->unit_serial_number, inq->usn, MAX_STRING_SIZE); + } else if (strncmp(iscsi->unit_serial_number, inq->usn, MAX_STRING_SIZE)) { + iscsi_set_error(iscsi, "unit serial number mismatch. got [%s] expected [%s]", + inq->usn, iscsi->unit_serial_number); + status = 1; + } else { + ISCSI_LOG(iscsi, 2, "successfully validated unit serial number [%s]", inq->usn); + } } else { - ISCSI_LOG(iscsi, 2, "successfully validated unit serial number [%s]", inq->usn); + iscsi_set_error(iscsi, "iscsi_inquiry_task datain_unmarshall failed. could not read vpd page 0x80."); + status = 1; } } else { iscsi_set_error(iscsi, "iscsi_inquiry_task failed. could not read vpd page 0x80."); From 247133c9e26bab77f39f73a57c256981cdc07bf9 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 11 Sep 2025 19:51:00 +0000 Subject: [PATCH 2/2] feat: allow targetname redirect this patch adds an non-RFC extenstion to the redirect login response which allows a target to temporarily redirect not only to a different target address but also to a different targetname. This is needed to allow scenarious in active/active storage clusters where each node had its own targetname, but maps the same volumes behind equal LUN ids. For this non-RFC behaviour the environment variable LIBISCSI_ALLLOW_TARGETNAME_REDIRECT has to be set. Signed-off-by: Peter Lieven --- include/iscsi-private.h | 3 ++- lib/login.c | 39 +++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 94fd825..66413da 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -112,13 +112,14 @@ struct iscsi_context { char initiator_name[MAX_ISCSI_NAME_SIZE+1]; char target_name[MAX_ISCSI_NAME_SIZE+1]; char target_address[MAX_STRING_SIZE+1]; /* If a redirect */ + char target_name2[MAX_ISCSI_NAME_SIZE+1]; /* If a redirect */ char connected_portal[MAX_STRING_SIZE+1]; char portal[MAX_STRING_SIZE+1]; char alias[MAX_STRING_SIZE+1]; char bind_interfaces[MAX_STRING_SIZE+1]; char unit_serial_number[MAX_STRING_SIZE+1]; - enum iscsi_chap_auth chap_auth; + enum iscsi_chap_auth chap_auth; char user[MAX_STRING_SIZE+1]; char passwd[MAX_STRING_SIZE+1]; char chap_c[MAX_CHAP_C_LENGTH+1]; diff --git a/lib/login.c b/lib/login.c index 0dbe3de..705d259 100644 --- a/lib/login.c +++ b/lib/login.c @@ -117,11 +117,19 @@ iscsi_login_add_targetname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) return -1; } - if (snprintf(str, MAX_STRING_SIZE, "TargetName=%s", iscsi->target_name) == -1) { - iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); - return -1; + if (iscsi->target_address[0] && iscsi->target_name2[0] && + getenv("LIBISCSI_ALLOW_TARGETNAME_REDIRECT") != NULL) { + if (snprintf(str, MAX_STRING_SIZE, "TargetName=%s", iscsi->target_name2) == -1) { + iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); + return -1; + } + ISCSI_LOG(iscsi, 2, "rewriting TargetName to %s (non-RFC-compliant!)", iscsi->target_name2); + } else { + if (snprintf(str, MAX_STRING_SIZE, "TargetName=%s", iscsi->target_name) == -1) { + iscsi_set_error(iscsi, "Out-of-memory: aprintf failed."); + return -1; + } } - if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); @@ -553,7 +561,7 @@ iscsi_login_add_authmethod(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) return 0; } - + static int iscsi_login_add_authalgorithm(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { @@ -576,7 +584,7 @@ iscsi_login_add_authalgorithm(struct iscsi_context *iscsi, struct iscsi_pdu *pdu return 0; } - + static int iscsi_login_add_chap_username(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { @@ -880,7 +888,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu char digest[MAX_CHAP_R_SIZE]; int i; int chap_r_size = 0; - + if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) { return 0; @@ -903,7 +911,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu chap_r_size = 32; break; } - + compute_chap_r(iscsi, iscsi->chap_i, (unsigned char *)iscsi->passwd, (unsigned char *)iscsi->chap_c, @@ -938,7 +946,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu if (iscsi->target_user[0]) { char target_chap_c[MAX_CHAP_R_SIZE * 2] = {0}; char target_chap_c_hex[MAX_CHAP_R_SIZE * 4 + 1] = { 0 }; - + iscsi->target_chap_i++; snprintf(str, MAX_STRING_SIZE, "CHAP_I=%d", iscsi->target_chap_i); @@ -998,7 +1006,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, " giving up."); return -1; } - + if (iscsi->is_loggedin != 0) { iscsi_set_error(iscsi, "Trying to login while already logged " "in."); @@ -1330,6 +1338,10 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, strncpy(iscsi->target_address,ptr+14,MAX_STRING_SIZE); } + if (!strncmp(ptr, "TargetName=", 11)) { + strncpy(iscsi->target_name2,ptr+11,MAX_ISCSI_NAME_SIZE); + } + if (!strncmp(ptr, "HeaderDigest=", 13)) { if (!strcmp(ptr + 13, "CRC32C")) { iscsi->want_header_digest @@ -1452,7 +1464,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, chap_r_size = 32; break; } - + if (len != 9 + 2 * chap_r_size) { iscsi_set_error(iscsi, "Wrong size of CHAP_R" " received from target."); @@ -1486,7 +1498,10 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, } if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) { - ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address); + ISCSI_LOG(iscsi, 2, "target requests redirect to portal %s",iscsi->target_address); + if (iscsi->target_name2[0] && getenv("LIBISCSI_ALLOW_TARGETNAME_REDIRECT") != NULL) { + ISCSI_LOG(iscsi, 2, "target requests redirect to targetname %s (non-RFC-compliant!)",iscsi->target_name2); + } if (pdu->callback) { pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL, pdu->private_data);