static int iscsi_login_add_chap_username(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) { return 0; } strncpy(str,"CHAP_N=",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); return -1; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)iscsi->user, strlen(iscsi->user) +1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data " "failed."); return -1; } return 0; }
static int iscsi_login_add_targetname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send TargetName during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG && iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) { return 0; } if (!iscsi->target_name[0]) { iscsi_set_error(iscsi, "Trying normal connect but " "target name not set."); 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_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); return -1; } return 0; }
static int iscsi_login_add_sessiontype(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send TargetName during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG && iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) { return 0; } switch (iscsi->session_type) { case ISCSI_SESSION_DISCOVERY: strncpy(str,"SessionType=Discovery",MAX_STRING_SIZE); break; case ISCSI_SESSION_NORMAL: strncpy(str,"SessionType=Normal",MAX_STRING_SIZE); break; default: iscsi_set_error(iscsi, "Can not handle sessions %d yet.", iscsi->session_type); 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."); return -1; } return 0; }
int iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data) { struct iscsi_pdu *pdu; char *str; if (iscsi->session_type != ISCSI_SESSION_DISCOVERY) { iscsi_set_error(iscsi, "Trying to do discovery on " "non-discovery session."); return -1; } pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_TEXT_REQUEST, ISCSI_PDU_TEXT_RESPONSE, iscsi_itt_post_increment(iscsi), ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "text pdu."); return -1; } /* immediate */ iscsi_pdu_set_immediate(pdu); /* cmdsn is not increased if Immediate delivery*/ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); /* flags */ iscsi_pdu_set_pduflags(pdu, ISCSI_PDU_TEXT_FINAL); /* target transfer tag */ iscsi_pdu_set_ttt(pdu, 0xffffffff); /* sendtargets */ str = (char *)"SendTargets=All"; 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."); iscsi->drv->free_pdu(iscsi, pdu); return -1; } pdu->callback = cb; pdu->private_data = private_data; if (iscsi_queue_pdu(iscsi, pdu) != 0) { iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi " "text pdu."); iscsi->drv->free_pdu(iscsi, pdu); return -1; } return 0; }
int iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, unsigned char *data, int len, void *private_data) { struct iscsi_pdu *pdu; if (iscsi == NULL) { printf("trying to send nop-out on NULL context\n"); return -1; } if (iscsi->is_loggedin == 0) { printf("trying send nop-out while not logged in\n"); return -2; } pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NOP_IN); if (pdu == NULL) { printf("Failed to allocate nop-out pdu\n"); return -3; } /* immediate flag */ iscsi_pdu_set_immediate(pdu); /* flags */ iscsi_pdu_set_pduflags(pdu, 0x80); /* ttt */ iscsi_pdu_set_ttt(pdu, 0xffffffff); /* lun */ iscsi_pdu_set_lun(pdu, 2); /* cmdsn is not increased if Immediate delivery*/ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); pdu->cmdsn = iscsi->cmdsn; // iscsi->cmdsn++; pdu->callback = cb; pdu->private_data = private_data; if (iscsi_pdu_add_data(iscsi, pdu, data, len) != 0) { printf("Failed to add outdata to nop-out\n"); iscsi_free_pdu(iscsi, pdu); return -4; } if (iscsi_queue_pdu(iscsi, pdu) != 0) { printf("failed to queue iscsi nop-out pdu\n"); iscsi_free_pdu(iscsi, pdu); return -5; } return 0; }
static int iscsi_login_add_authalgorithm(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM) { return 0; } strncpy(str,"CHAP_A=5",MAX_STRING_SIZE); 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."); return -1; } return 0; }
static int iscsi_login_add_authmethod(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) { return 0; } strncpy(str,"AuthMethod=CHAP,None",MAX_STRING_SIZE); 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."); return -1; } return 0; }
static int iscsi_login_add_errorrecoverylevel(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send ErrorRecoveryLevel during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } strncpy(str,"ErrorRecoveryLevel=0",MAX_STRING_SIZE); 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."); return -1; } return 0; }
static int iscsi_login_add_datasequenceinorder(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send DataSequenceInOrder during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } strncpy(str,"DataSequenceInOrder=Yes",MAX_STRING_SIZE); 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."); return -1; } return 0; }
static int iscsi_login_add_maxrecvdatasegmentlength(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send MaxRecvDataSegmentLength during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } if (snprintf(str, MAX_STRING_SIZE, "MaxRecvDataSegmentLength=%d", iscsi->initiator_max_recv_data_segment_length) == -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."); return -1; } return 0; }
static int iscsi_login_add_alias(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send InitiatorAlias during opneg or the first leg of secneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG && iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) { return 0; } if (snprintf(str, MAX_STRING_SIZE, "InitiatorAlias=%s", iscsi->alias) == -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."); return -1; } return 0; }
static int iscsi_login_add_immediatedata(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send ImmediateData during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } if (snprintf(str, MAX_STRING_SIZE, "ImmediateData=%s", iscsi->want_immediate_data == ISCSI_IMMEDIATE_DATA_NO ? "No" : "Yes") == -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."); return -1; } return 0; }
static int iscsi_login_add_initialr2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send InitialR2T during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } if (snprintf(str, MAX_STRING_SIZE, "InitialR2T=%s", iscsi->want_initial_r2t == ISCSI_INITIAL_R2T_NO ? "No" : "Yes") == -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."); return -1; } return 0; }
static int iscsi_login_add_headerdigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; /* We only send HeaderDigest during opneg */ if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_OPNEG) { return 0; } switch (iscsi->want_header_digest) { case ISCSI_HEADER_DIGEST_NONE: strncpy(str,"HeaderDigest=None",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_NONE_CRC32C: strncpy(str,"HeaderDigest=None,CRC32C",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_CRC32C_NONE: strncpy(str,"HeaderDigest=CRC32C,None",MAX_STRING_SIZE); break; case ISCSI_HEADER_DIGEST_CRC32C: strncpy(str,"HeaderDigest=CRC32C",MAX_STRING_SIZE); break; default: iscsi_set_error(iscsi, "invalid header digest value"); 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."); return -1; } return 0; }
static int iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { char str[MAX_STRING_SIZE+1]; char * strp; unsigned char c, cc[2]; unsigned char digest[16]; gcry_md_hd_t ctx; int i; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG || iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) { return 0; } gcry_md_open(&ctx, GCRY_MD_MD5, 0); if (!ctx) { iscsi_set_error(iscsi, "Cannot create MD5 algorithm"); return -1; } if (!iscsi->chap_c[0]) { iscsi_set_error(iscsi, "No CHAP challenge found"); return -1; } gcry_md_putc(ctx, iscsi->chap_i); gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd)); strp = iscsi->chap_c; while (*strp != 0) { c = (h2i(strp[0]) << 4) | h2i(strp[1]); strp += 2; gcry_md_putc(ctx, c); } memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest)); gcry_md_close(ctx); strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed."); return -1; } for (i=0; i<16; i++) { c = digest[i]; cc[0] = i2h((c >> 4)&0x0f); cc[1] = i2h((c )&0x0f); if (iscsi_pdu_add_data(iscsi, pdu, &cc[0], 2) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data " "failed."); return -1; } } c = 0; if (iscsi_pdu_add_data(iscsi, pdu, &c, 1) != 0) { iscsi_set_error(iscsi, "Out-of-memory: pdu add data " "failed."); return -1; } return 0; }
static int iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, struct scsi_task *task, iscsi_command_cb cb, struct iscsi_data *data, void *private_data) { struct iscsi_pdu *pdu; struct iscsi_scsi_cbdata *scsi_cbdata; int flags; if (iscsi == NULL) { printf("trying to send command on NULL context\n"); scsi_free_scsi_task(task); return -1; } if (iscsi->session_type != ISCSI_SESSION_NORMAL) { printf("Trying to send command on discovery session\n"); scsi_free_scsi_task(task); return -2; } if (iscsi->is_loggedin == 0) { printf("Trying to send command while not logged in\n"); scsi_free_scsi_task(task); return -3; } scsi_cbdata = malloc(sizeof(struct iscsi_scsi_cbdata)); if (scsi_cbdata == NULL) { printf("failed to allocate scsi cbdata\n"); scsi_free_scsi_task(task); return -4; } bzero(scsi_cbdata, sizeof(struct iscsi_scsi_cbdata)); scsi_cbdata->task = task; scsi_cbdata->callback = cb; scsi_cbdata->private_data = private_data; pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_REQUEST, ISCSI_PDU_SCSI_RESPONSE); if (pdu == NULL) { printf("Failed to allocate text pdu\n"); iscsi_free_scsi_cbdata(scsi_cbdata); return -5; } pdu->scsi_cbdata = scsi_cbdata; /* flags */ flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE; switch (task->xfer_dir) { case SCSI_XFER_NONE: break; case SCSI_XFER_READ: flags |= ISCSI_PDU_SCSI_READ; break; case SCSI_XFER_WRITE: flags |= ISCSI_PDU_SCSI_WRITE; if (data == NULL) { printf("DATA-OUT command but data == NULL\n"); iscsi_free_pdu(iscsi, pdu); return -5; } if (data->size != task->expxferlen) { printf("data size:%d is not same as expected data transfer length:%d\n", data->size, task->expxferlen); iscsi_free_pdu(iscsi, pdu); return -7; } if (iscsi_pdu_add_data(iscsi, pdu, data->data, data->size) != 0) { printf("Failed to add outdata to the pdu\n"); iscsi_free_pdu(iscsi, pdu); return -6; } break; } iscsi_pdu_set_pduflags(pdu, flags); /* lun */ iscsi_pdu_set_lun(pdu, lun); /* expxferlen */ iscsi_pdu_set_expxferlen(pdu, task->expxferlen); /* cmdsn */ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); pdu->cmdsn = iscsi->cmdsn; iscsi->cmdsn++; /* exp statsn */ iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1); /* cdb */ iscsi_pdu_set_cdb(pdu, task); pdu->callback = iscsi_scsi_response_cb; pdu->private_data = scsi_cbdata; if (iscsi_queue_pdu(iscsi, pdu) != 0) { printf("failed to queue iscsi scsi pdu\n"); iscsi_free_pdu(iscsi, pdu); return -6; } return 0; }
int iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, unsigned char *data, int len, void *private_data) { struct iscsi_pdu *pdu; if (iscsi->old_iscsi || iscsi->pending_reconnect) { ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6, "NOP Out Send NOT SEND while reconnecting (nops_in_flight: %d, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)", iscsi->nops_in_flight, iscsi->maxcmdsn, iscsi->expcmdsn); return 0; } if (iscsi->is_loggedin == 0) { iscsi_set_error(iscsi, "trying to send nop-out while not " "logged in"); return -1; } pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NOP_IN, iscsi_itt_post_increment(iscsi), ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Failed to allocate nop-out pdu"); return -1; } /* flags */ iscsi_pdu_set_pduflags(pdu, 0x80); /* ttt */ iscsi_pdu_set_ttt(pdu, 0xffffffff); /* lun */ iscsi_pdu_set_lun(pdu, 0); /* cmdsn */ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn++); pdu->callback = cb; pdu->private_data = private_data; if (data != NULL && len > 0) { if (iscsi_pdu_add_data(iscsi, pdu, data, len) != 0) { iscsi_set_error(iscsi, "Failed to add outdata to nop-out"); iscsi->drv->free_pdu(iscsi, pdu); return -1; } } if (iscsi_queue_pdu(iscsi, pdu) != 0) { iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu"); iscsi->drv->free_pdu(iscsi, pdu); return -1; } iscsi->nops_in_flight++; ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6, "NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)", iscsi->nops_in_flight, pdu->cmdsn, pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn); return 0; }
int iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data) { struct iscsi_pdu *pdu; char *str; int ret; if (iscsi == NULL) { printf("trying to login on NULL context\n"); return -1; } if (iscsi->is_loggedin != 0) { printf("trying to login while already logged in\n"); return -2; } switch (iscsi->session_type) { case ISCSI_SESSION_DISCOVERY: case ISCSI_SESSION_NORMAL: break; default: printf("trying to login without setting session type\n"); return -3; } pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGIN_REQUEST, ISCSI_PDU_LOGIN_RESPONSE); if (pdu == NULL) { printf("Failed to allocate login pdu\n"); return -4; } /* login request */ iscsi_pdu_set_immediate(pdu); /* flags */ iscsi_pdu_set_pduflags(pdu, ISCSI_PDU_LOGIN_TRANSIT|ISCSI_PDU_LOGIN_CSG_OPNEG|ISCSI_PDU_LOGIN_NSG_FF); /* initiator name */ if (asprintf(&str, "InitiatorName=%s", iscsi->initiator_name) == -1) { printf("asprintf failed\n"); iscsi_free_pdu(iscsi, pdu); return -5; } ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1); free(str); if (ret != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -6; } /* optional alias */ if (iscsi->alias) { if (asprintf(&str, "InitiatorAlias=%s", iscsi->alias) == -1) { printf("asprintf failed\n"); iscsi_free_pdu(iscsi, pdu); return -7; } ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1); free(str); if (ret != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -8; } } /* target name */ if (iscsi->session_type == ISCSI_SESSION_NORMAL) { if (iscsi->target_name == NULL) { printf("trying normal connect but target name not set\n"); iscsi_free_pdu(iscsi, pdu); return -9; } if (asprintf(&str, "TargetName=%s", iscsi->target_name) == -1) { printf("asprintf failed\n"); iscsi_free_pdu(iscsi, pdu); return -10; } ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1); free(str); if (ret != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -11; } } /* session type */ switch (iscsi->session_type) { case ISCSI_SESSION_DISCOVERY: str = "SessionType=Discovery"; break; case ISCSI_SESSION_NORMAL: str = "SessionType=Normal"; break; default: printf("can not handle sessions %d yet\n", iscsi->session_type); return -12; } if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -13; } str = "HeaderDigest=None"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -14; } str = "DataDigest=None"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -15; } str = "InitialR2T=Yes"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -16; } str = "ImmediateData=Yes"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -17; } str = "MaxBurstLength=262144"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -18; } str = "FirstBurstLength=262144"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -19; } str = "MaxRecvDataSegmentLength=262144"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -20; } str = "DataPDUInOrder=Yes"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -21; } str = "DataSequenceInOrder=Yes"; if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) { printf("pdu add data failed\n"); iscsi_free_pdu(iscsi, pdu); return -22; } pdu->callback = cb; pdu->private_data = private_data; if (iscsi_queue_pdu(iscsi, pdu) != 0) { printf("failed to queue iscsi login pdu\n"); iscsi_free_pdu(iscsi, pdu); return -23; } return 0; }