📄 iscsi-login.c
字号:
return 0; } } else if (iscsi_find_key_value("TargetPortalGroupTag", text, end, &value, &value_end)) { /* We should have already obtained this via discovery. * We've already picked an isid, so the most we can do is confirm we reached * the portal group we were expecting to. */ int tag = iscsi_strtoul(value, NULL, 0); if (session->portal_group_tag >= 0) { if (tag != session->portal_group_tag) { logmsg(AS_ERROR, "session %p portal group tag mismatch, expected %u, actual %u\n", session, session->portal_group_tag, tag); return 0; } } else { /* we now know the tag */ session->portal_group_tag = tag; } text = value_end; } else if (iscsi_find_key_value("InitialR2T", text, end, &value, &value_end)) { if (value && iscsi_strcmp(value, "Yes") == 0) session->InitialR2T = 1; else session->InitialR2T = 0; text = value_end; } else if (iscsi_find_key_value("ImmediateData", text, end, &value, &value_end)) { if (value && iscsi_strcmp(value, "Yes") == 0) session->ImmediateData = 1; else session->ImmediateData = 0; text = value_end; } else if (iscsi_find_key_value("MaxRecvDataSegmentLength", text, end, &value, &value_end)) { /* FIXME: no octal */ session->MaxXmitDataSegmentLength = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("FirstBurstLength", text, end, &value, &value_end)) { /* FIXME: no octal */ session->FirstBurstLength = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("MaxBurstLength", text, end, &value, &value_end)) { /* we don't really care, since it's a limit on the target's R2Ts, but record it anwyay */ /* FIXME: no octal, and draft16 says we MUST NOT send more than MaxBurstLength */ session->MaxBurstLength = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("HeaderDigest", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "None")) { logmsg(AS_ERROR, "session %p can't accept %s\n", session, text); return 0; } text = value_end; } else if (iscsi_find_key_value("DataDigest", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "None")) { logmsg(AS_ERROR, "session %p can't accept %s\n", session, text); return 0; } text = value_end; } else if (iscsi_find_key_value("DefaultTime2Wait", text, end, &value, &value_end)) { session->DefaultTime2Wait = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("DefaultTime2Retain", text, end, &value, &value_end)) { session->DefaultTime2Retain = iscsi_strtoul(value, NULL, 0); text = value_end; } else if (iscsi_find_key_value("OFMarker", text, end, &value, &value_end)) { /* result function is AND, target must honor our No */ text = value_end; } else if (iscsi_find_key_value("OFMarkInt", text, end, &value, &value_end)) { /* we don't do markers, so we don't care */ text = value_end; } else if (iscsi_find_key_value("IFMarker", text, end, &value, &value_end)) { /* result function is AND, target must honor our No */ text = value_end; } else if (iscsi_find_key_value("IFMarkInt", text, end, &value, &value_end)) { /* we don't do markers, so we don't care */ text = value_end; } else if (iscsi_find_key_value("DataPDUInOrder", text, end, &value, &value_end)) { if (value && iscsi_strcmp(value, "Yes") == 0) session->DataPDUInOrder = 1; else session->DataPDUInOrder = 0; text = value_end; } else if (iscsi_find_key_value("DataSequenceInOrder", text, end, &value, &value_end)) { if (value && iscsi_strcmp(value, "Yes") == 0) session->DataSequenceInOrder = 1; else session->DataSequenceInOrder = 0; text = value_end; } else if (iscsi_find_key_value("MaxOutstandingR2T", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "1")) { logmsg(AS_ERROR, "session %p can't accept MaxOutstandingR2T %s\n", session, value); return 0; } text = value_end; } else if (iscsi_find_key_value("MaxConnections", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "1")) { logmsg(AS_ERROR, "session %p can't accept MaxConnections %s\n", session, value); return 0; } text = value_end; } else if (iscsi_find_key_value("ErrorRecoveryLevel", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "0")) { logmsg(AS_ERROR, "session %p can't accept ErrorRecovery %s\n", session, value); return 0; } text = value_end; } else if (iscsi_find_key_value("X-com.cisco.protocol", text, end, &value, &value_end)) { if (iscsi_strcmp(value, "NotUnderstood") && iscsi_strcmp(value, "draft16")) { /* if we didn't get a compatible protocol, fail */ logmsg(AS_ERROR, "can't accept protocol %s\n", value); return 0; } text = value_end; } else if (iscsi_find_key_value("X-com.cisco.PingTimeout", text, end, &value, &value_end)) { /* don't care */ text = value_end; } else { /* FIXME: we may want to ignore X- keys sent by * the target, but that would require us to have * another PDU buffer so that we can generate a * response while we still know what keys we * received, so that we can reply with a * NotUnderstood response. For now, reject logins * with keys we don't understand. Another option is * to silently ignore them, and see if the target has * a problem with that. The danger there is we may * get caught in an infinite loop where we send an empty * PDU requesting a phase transition, and the target * keeps sending an empty PDU denying a phase transition * (because we haven't replied to it's key yet). */ logmsg(AS_ERROR, "failed to recognize text %s\n", text); return 0; } break; } default: return 0; } } if (session->current_phase == ISCSI_SECURITY_NEGOTIATION_PHASE) { switch (iscsiAuthClientRecvEnd(session->auth_client, null_callback, NULL, NULL)) { default: case iscsiAuthStatusNoError: /* treat this as an error, since we should get a different code */ case iscsiAuthStatusError: logmsg(AS_ERROR, "session %p error authenticating with target %s\n", session, session->TargetName); return 0; case iscsiAuthStatusInProgress: /* this should only occur if we were authenticating the target, * which we don't do yet, so treat this as an error. */ logmsg(AS_ERROR, "session %p error authenticating target %s\n", session, session->TargetName); return 0; case iscsiAuthStatusContinue: /* continue sending PDUs */ break; case iscsiAuthStatusPass: logmsg(AS_INFO, "session %p authenticated by target %s\n", session, session->TargetName); break; case iscsiAuthStatusFail: logmsg(AS_ERROR, "session %p failed authentication with target %s\n", session, session->TargetName); return 0; } } /* record some of the PDU fields for later use */ session->tsid = iscsi_ntohs(login_rsp_pdu->tsid); session->ExpCmdSn = iscsi_ntohl(login_rsp_pdu->expcmdsn); session->MaxCmdSn = iscsi_ntohl(login_rsp_pdu->maxcmdsn); if (login_rsp_pdu->status_class == STATUS_CLASS_SUCCESS) session->ExpStatSn = iscsi_ntohl(login_rsp_pdu->statsn) + 1; if (login_rsp_pdu->tbit) { /* advance to the next phase */ session->partial_response = 0; session->current_phase = login_rsp_pdu->next; } else { /* we got a partial response, don't advance, more negotiation to do */ session->partial_response = 1; } return 1;}int iscsi_make_text_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length){ struct IscsiTextHdr *text_pdu = (struct IscsiTextHdr *)pdu; /* initialize the PDU header */ memset(text_pdu, 0, sizeof(*text_pdu)); text_pdu->opcode = ISCSI_OP_TEXT_CMD; text_pdu->itt = iscsi_htonl(session->itt); text_pdu->ttt = RSVD_TASK_TAG; text_pdu->cmdsn = iscsi_htonl(session->CmdSn++); text_pdu->expstatsn = iscsi_htonl(session->ExpStatSn); return 1;}int iscsi_make_login_pdu(iscsi_session_t *session, struct IscsiHdr *pdu, char *data, int max_data_length){ int tbit = 0; char value[iscsiAuthStringMaxLength]; struct IscsiLoginHdr *login_pdu = (struct IscsiLoginHdr *)pdu; /* initialize the PDU header */ memset(login_pdu, 0, sizeof(*login_pdu)); login_pdu->opcode = ISCSI_OP_LOGIN_CMD | ISCSI_OP_IMMEDIATE; login_pdu->cid = 0; memcpy(login_pdu->isid, session->isid, sizeof(session->isid)); login_pdu->tsid = 0; login_pdu->cmdsn = iscsi_htonl(session->CmdSn); /* don't increment on immediate */ login_pdu->min_version = ISCSI_DRAFT16_VERSION; login_pdu->max_version = ISCSI_DRAFT16_VERSION; /* we have to send 0 until full-feature phase */ login_pdu->expstatsn = 0; /* iscsi_htonl(session->ExpStatSn); */ /* the very first Login PDU has some additional requirements, * and we need to decide what phase to start in. */ if (session->current_phase == ISCSI_INITIAL_LOGIN_PHASE) { if (session->InitiatorName && session->InitiatorName[0]) { if (!iscsi_add_text(session, pdu, data, max_data_length, "InitiatorName", session->InitiatorName)) return 0; } else { logmsg(AS_ERROR, "InitiatorName is required on the first Login PDU\n"); return 0; } if (session->InitiatorAlias && session->InitiatorAlias[0]) { if (!iscsi_add_text(session, pdu, data, max_data_length, "InitiatorAlias", session->InitiatorAlias)) return 0; } if (session->TargetName[0] != '\0') { if (!iscsi_add_text(session, pdu, data, max_data_length, "TargetName", session->TargetName)) return 0; } if (!iscsi_add_text(session, pdu, data, max_data_length, "SessionType", (session->type == ISCSI_SESSION_TYPE_DISCOVERY) ? "Discovery" : "Normal")) return 0; if (session->auth_client) { /* we're prepared to do authentication */ session->current_phase = session->next_phase = ISCSI_SECURITY_NEGOTIATION_PHASE; } else { /* can't do any authentication, skip that phase */ session->current_phase = session->next_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -