Login: remember what the TargetAddress returned during login is so we can

handle redirect 'errors'.
This commit is contained in:
Ronnie Sahlberg
2011-02-25 15:35:49 +11:00
parent e9749ee68c
commit 356a6571bb
4 changed files with 59 additions and 29 deletions
+1
View File
@@ -55,6 +55,7 @@ enum iscsi_immediate_data {
struct iscsi_context { struct iscsi_context {
const char *initiator_name; const char *initiator_name;
const char *target_name; const char *target_name;
const char *target_address; /* If a redirect */
const char *alias; const char *alias;
const char *user; const char *user;
+5
View File
@@ -151,6 +151,11 @@ int iscsi_set_alias(struct iscsi_context *iscsi, const char *alias);
*/ */
int iscsi_set_targetname(struct iscsi_context *iscsi, const char *targetname); int iscsi_set_targetname(struct iscsi_context *iscsi, const char *targetname);
/*
* This function returns any target address supplied in a login response when
* the target has moved.
*/
const char *iscsi_get_target_address(struct iscsi_context *iscsi);
/* Type of iscsi sessions. Discovery sessions are used to query for what /* Type of iscsi sessions. Discovery sessions are used to query for what
* targets exist behind the portal connected to. Normal sessions are used to * targets exist behind the portal connected to. Normal sessions are used to
+10
View File
@@ -202,6 +202,9 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
free(discard_const(iscsi->target_name)); free(discard_const(iscsi->target_name));
iscsi->target_name = NULL; iscsi->target_name = NULL;
free(discard_const(iscsi->target_address));
iscsi->target_address = NULL;
free(discard_const(iscsi->alias)); free(discard_const(iscsi->alias));
iscsi->alias = NULL; iscsi->alias = NULL;
@@ -257,6 +260,13 @@ iscsi_get_error(struct iscsi_context *iscsi)
return iscsi->error_string; return iscsi->error_string;
} }
const char *
iscsi_get_target_address(struct iscsi_context *iscsi)
{
return iscsi->target_address;
}
int int
iscsi_set_header_digest(struct iscsi_context *iscsi, iscsi_set_header_digest(struct iscsi_context *iscsi,
enum iscsi_header_digest header_digest) enum iscsi_header_digest header_digest)
+43 -29
View File
@@ -886,6 +886,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
static const char *login_error_str(int status) static const char *login_error_str(int status)
{ {
switch (status) { switch (status) {
case 0x0100: return "Target moved (unknown)"; /* Some don't set the detail */
case 0x0101: return "Target moved temporarily"; case 0x0101: return "Target moved temporarily";
case 0x0102: return "Target moved permanently"; case 0x0102: return "Target moved permanently";
case 0x0200: return "Initiator error"; case 0x0200: return "Initiator error";
@@ -913,17 +914,10 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
struct iscsi_in_pdu *in) struct iscsi_in_pdu *in)
{ {
int status; int status;
unsigned char *ptr = in->data; char *ptr = (char *)in->data;
int size = in->data_pos; int size = in->data_pos;
status = ntohs(*(uint16_t *)&in->hdr[36]); status = ntohs(*(uint16_t *)&in->hdr[36]);
if (status != 0) {
iscsi_set_error(iscsi, "Failed to log in to target. Status: %s(%d)",
login_error_str(status), status);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
return 0;
}
iscsi->statsn = ntohs(*(uint16_t *)&in->hdr[24]); iscsi->statsn = ntohs(*(uint16_t *)&in->hdr[24]);
@@ -936,7 +930,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
while (size > 0) { while (size > 0) {
int len; int len;
len = strlen((char *)ptr); len = strlen(ptr);
if (len == 0) { if (len == 0) {
break; break;
@@ -951,8 +945,20 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
} }
/* parse the strings */ /* parse the strings */
if (!strncmp((char *)ptr, "HeaderDigest=", 13)) { if (!strncmp(ptr, "TargetAddress=", 14)) {
if (!strcmp((char *)ptr + 13, "CRC32C")) { free(discard_const(iscsi->target_address));
iscsi->target_address = strdup(ptr+14);
if (iscsi->target_address == NULL) {
iscsi_set_error(iscsi, "Failed to allocate"
" target address");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
return -1;
}
}
if (!strncmp(ptr, "HeaderDigest=", 13)) {
if (!strcmp(ptr + 13, "CRC32C")) {
iscsi->header_digest iscsi->header_digest
= ISCSI_HEADER_DIGEST_CRC32C; = ISCSI_HEADER_DIGEST_CRC32C;
iscsi->want_header_digest iscsi->want_header_digest
@@ -965,53 +971,53 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
} }
} }
if (!strncmp((char *)ptr, "FirstBurstLength=", 17)) { if (!strncmp(ptr, "FirstBurstLength=", 17)) {
iscsi->first_burst_length = strtol((char *)ptr + 17, NULL, 10); iscsi->first_burst_length = strtol(ptr + 17, NULL, 10);
} }
if (!strncmp((char *)ptr, "InitialR2T=", 11)) { if (!strncmp(ptr, "InitialR2T=", 11)) {
if (!strcmp((char *)ptr + 11, "No")) { if (!strcmp(ptr + 11, "No")) {
iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_NO; iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_NO;
} else { } else {
iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_YES; iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_YES;
} }
} }
if (!strncmp((char *)ptr, "ImmediateData=", 14)) { if (!strncmp(ptr, "ImmediateData=", 14)) {
if (!strcmp((char *)ptr + 14, "No")) { if (!strcmp(ptr + 14, "No")) {
iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO; iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
} else { } else {
iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_YES; iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_YES;
} }
} }
if (!strncmp((char *)ptr, "MaxBurstLength=", 15)) { if (!strncmp(ptr, "MaxBurstLength=", 15)) {
iscsi->max_burst_length = strtol((char *)ptr + 15, NULL, 10); iscsi->max_burst_length = strtol(ptr + 15, NULL, 10);
} }
if (!strncmp((char *)ptr, "MaxRecvDataSegmentLength=", 25)) { if (!strncmp(ptr, "MaxRecvDataSegmentLength=", 25)) {
iscsi->target_max_recv_data_segment_length = strtol((char *)ptr + 25, NULL, 10); iscsi->target_max_recv_data_segment_length = strtol(ptr + 25, NULL, 10);
} }
if (!strncmp((char *)ptr, "AuthMethod=", 11)) { if (!strncmp(ptr, "AuthMethod=", 11)) {
if (!strcmp((char *)ptr + 11, "CHAP")) { if (!strcmp(ptr + 11, "CHAP")) {
iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM; iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM;
} }
} }
if (!strncmp((char *)ptr, "CHAP_A=", 7)) { if (!strncmp(ptr, "CHAP_A=", 7)) {
iscsi->chap_a = atoi((char *)ptr+7); iscsi->chap_a = atoi(ptr+7);
iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE; iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE;
} }
if (!strncmp((char *)ptr, "CHAP_I=", 7)) { if (!strncmp(ptr, "CHAP_I=", 7)) {
iscsi->chap_i = atoi((char *)ptr+7); iscsi->chap_i = atoi(ptr+7);
iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE; iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE;
} }
if (!strncmp((char *)ptr, "CHAP_C=0x", 9)) { if (!strncmp(ptr, "CHAP_C=0x", 9)) {
free(iscsi->chap_c); free(iscsi->chap_c);
iscsi->chap_c = strdup((char *)ptr+9); iscsi->chap_c = strdup(ptr+9);
if (iscsi->chap_c == NULL) { if (iscsi->chap_c == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: Failed to strdup CHAP challenge."); iscsi_set_error(iscsi, "Out-of-memory: Failed to strdup CHAP challenge.");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, pdu->private_data); pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, pdu->private_data);
@@ -1024,6 +1030,14 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
size -= len + 1; size -= len + 1;
} }
if (status != 0) {
iscsi_set_error(iscsi, "Failed to log in to target. Status: %s(%d)",
login_error_str(status), status);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
return 0;
}
if (in->hdr[1] & ISCSI_PDU_LOGIN_TRANSIT) { if (in->hdr[1] & ISCSI_PDU_LOGIN_TRANSIT) {
iscsi->current_phase = (in->hdr[1] & ISCSI_PDU_LOGIN_NSG_FF) << 2; iscsi->current_phase = (in->hdr[1] & ISCSI_PDU_LOGIN_NSG_FF) << 2;
} }