void discoveryconnect_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { printf("Connected to iscsi socket status:0x%08x\n", status); if (status != 0) { printf("discoveryconnect_cb: connection failed status:%d\n", status); exit(10); } printf("connected, send login command\n"); iscsi_set_session_type(iscsi, ISCSI_SESSION_DISCOVERY); if (iscsi_login_async(iscsi, discoverylogin_cb, private_data) != 0) { printf("iscsi_login_async failed\n"); exit(10); } }
void normalconnect_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { printf("Connected to iscsi socket\n"); if (status != 0) { printf("normalconnect_cb: connection failed status:%d\n", status); exit(10); } printf("connected, send login command\n"); iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL); if (iscsi_login_async(iscsi, normallogin_cb, private_data) != 0) { printf("iscsi_login_async failed\n"); exit(10); } }
/* * Do a Discovery login to the target */ void iSCSILibWrapper::iSCSIDiscoveryLogin(void) { // Remove us from the background thread iSCSIBackGround::GetInstance().RemoveConnection(*this); if (!mClient.connected || mClient.error) { if (mClient.error) mErrorString.Format("%s: previous error prevents login: %s", __func__, iscsi_get_error(mIscsi)); else mErrorString.Format("%s: Login not possible without a connection!", __func__); mError = true; throw CException(mErrorString); } iscsi_set_session_type(mIscsi, ISCSI_SESSION_DISCOVERY); mClient.finished = 0; if (iscsi_login_async(mIscsi, discoverylogin_cb, this)) { mErrorString.Format("%s: iscsi_login_async for target %s failed: %s", __func__, mTarget.c_str(), iscsi_get_error(mIscsi)); mError = true; throw CException(mErrorString); } ServiceISCSIEvents(); // Add to the background task iSCSIBackGround::GetInstance().AddConnection(*this); }
int iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in) { uint32_t status, maxcmdsn, expcmdsn; char *ptr = (char *)in->data; int size = in->data_pos; status = scsi_get_uint16(&in->hdr[36]); iscsi->statsn = scsi_get_uint16(&in->hdr[24]); maxcmdsn = scsi_get_uint32(&in->hdr[32]); if (iscsi_serial32_compare(maxcmdsn, iscsi->maxcmdsn) > 0) { iscsi->maxcmdsn = maxcmdsn; } expcmdsn = scsi_get_uint32(&in->hdr[28]); if (iscsi_serial32_compare(expcmdsn, iscsi->expcmdsn) > 0) { iscsi->expcmdsn = expcmdsn; } /* XXX here we should parse the data returned in case the target * renegotiated some some parameters. * we should also do proper handshaking if the target is not yet * prepared to transition to the next stage */ while (size > 0) { char *end; int len; end = memchr(ptr, 0, size); if (end == NULL) { iscsi_set_error(iscsi, "NUL not found after offset %ld " "when parsing login data", (long)((unsigned char *)ptr - in->data)); pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, pdu->private_data); return -1; } len = end - ptr; if (len == 0) { break; } /* parse the strings */ if (!strncmp(ptr, "TargetAddress=", 14)) { strncpy(iscsi->target_address,ptr+14,MAX_STRING_SIZE); } if (!strncmp(ptr, "HeaderDigest=", 13)) { if (!strcmp(ptr + 13, "CRC32C")) { iscsi->want_header_digest = ISCSI_HEADER_DIGEST_CRC32C; } else { iscsi->want_header_digest = ISCSI_HEADER_DIGEST_NONE; } } if (!strncmp(ptr, "FirstBurstLength=", 17)) { iscsi->first_burst_length = strtol(ptr + 17, NULL, 10); } if (!strncmp(ptr, "InitialR2T=", 11)) { if (!strcmp(ptr + 11, "No")) { iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_NO; } else { iscsi->use_initial_r2t = ISCSI_INITIAL_R2T_YES; } } if (!strncmp(ptr, "ImmediateData=", 14)) { if (!strcmp(ptr + 14, "No")) { iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO; } else if (iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO) { /* If we negotiated NO, it doesnt matter what * the target said. ImmediateData is NO. */ iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO; } else { iscsi->use_immediate_data = ISCSI_IMMEDIATE_DATA_YES; } } if (!strncmp(ptr, "MaxBurstLength=", 15)) { iscsi->max_burst_length = strtol(ptr + 15, NULL, 10); } if (!strncmp(ptr, "MaxRecvDataSegmentLength=", 25)) { iscsi->target_max_recv_data_segment_length = strtol(ptr + 25, NULL, 10); } if (!strncmp(ptr, "AuthMethod=", 11)) { if (!strcmp(ptr + 11, "CHAP")) { iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM; } } if (!strncmp(ptr, "CHAP_A=", 7)) { iscsi->chap_a = atoi(ptr+7); iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE; } if (!strncmp(ptr, "CHAP_I=", 7)) { iscsi->chap_i = atoi(ptr+7); iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE; } if (!strncmp(ptr, "CHAP_C=0x", 9)) { strncpy(iscsi->chap_c,ptr+9,MAX_STRING_SIZE); iscsi->secneg_phase = ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE; } ptr += len + 1; size -= len + 1; } if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) { ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address); pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL, pdu->private_data); return 0; } 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) { iscsi->current_phase = (in->hdr[1] & ISCSI_PDU_LOGIN_NSG_FF) << 2; } if ((in->hdr[1] & ISCSI_PDU_LOGIN_TRANSIT) && (in->hdr[1] & ISCSI_PDU_LOGIN_NSG_FF) == ISCSI_PDU_LOGIN_NSG_FF) { iscsi->is_loggedin = 1; iscsi_itt_post_increment(iscsi); iscsi->header_digest = iscsi->want_header_digest; ISCSI_LOG(iscsi, 2, "login successful"); pdu->callback(iscsi, SCSI_STATUS_GOOD, NULL, pdu->private_data); } else { if (iscsi_login_async(iscsi, pdu->callback, pdu->private_data) != 0) { iscsi_set_error(iscsi, "Failed to send continuation login pdu"); pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, pdu->private_data); } } return 0; }
/* * Perform a NormalLogin against the target. Note, the target must be fully * specified here. */ void iSCSILibWrapper::iSCSINormalLogin(void) { // Remove us from the background thread iSCSIBackGround::GetInstance().RemoveConnection(*this); if (!mClient.connected || mClient.error) { if (mClient.error) mErrorString.Format("%s: previous error prevents login for target %s: %s", __func__, mTarget.c_str(), iscsi_get_error(mIscsi)); else mErrorString.Format("%s: Login to target %s not possible without a connection!", __func__, mTarget.c_str()); mError = true; throw CException(mErrorString); } mClient.finished = 0; iscsi_set_session_type(mIscsi, ISCSI_SESSION_NORMAL); iscsi_set_header_digest(mIscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE); if (iscsi_set_targetname(mIscsi, mTarget.c_str())) { mErrorString.Format("%s: failed to set target (%s) name: %s", __func__, mTarget.c_str(), iscsi_get_error(mIscsi)); mError = true; throw CException(mErrorString); } if (iscsi_login_async(mIscsi, discoverylogin_cb, this)) { mErrorString.Format("%s: iscsi_login_async to target %s failed: %s", __func__, mTarget.c_str(), iscsi_get_error(mIscsi)); mError = true; throw CException(mErrorString); } ServiceISCSIEvents(); // Add to the background task iSCSIBackGround::GetInstance().AddConnection(*this); // Now check to see if we have been redirected and recover the new address. if (mClient.error) { std::string errStr(iscsi_get_error(mIscsi)); if (errStr.find("Target moved temporarily(257)") != std::string::npos) { mRedirected = true; mNewAddress = std::string(iscsi_get_target_address(mIscsi)); } } }