⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iscsi-login.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* fill in text based on the phase */    switch (session->current_phase) {        case ISCSI_OP_PARMS_NEGOTIATION_PHASE: {            if (!session->partial_response) {                /* try to go to full feature phase */                login_pdu->curr = session->current_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE;                login_pdu->next = session->next_phase    = ISCSI_FULL_FEATURE_PHASE;                login_pdu->tbit = 1;                /* discovery sessions don't need most op params, but we may end up in this phase                  * if the target insists on it, or if we're skipping security phase.                 */                if (session->type == ISCSI_SESSION_TYPE_DISCOVERY)                    break;                /* request the desired settings the first time we are in this phase */                if (!iscsi_add_text(session, pdu, data, max_data_length, "InitialR2T", session->InitialR2T ? "Yes" : "No"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "ImmediateData", session->ImmediateData ? "Yes" : "No"))                    return 0;                iscsi_sprintf(value, "%d", session->MaxRecvDataSegmentLength);                if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxRecvDataSegmentLength", value))                    return 0;                iscsi_sprintf(value, "%d", session->MaxBurstLength);                if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxBurstLength", value))                    return 0;                iscsi_sprintf(value, "%d", session->FirstBurstLength);                if (!iscsi_add_text(session, pdu, data, max_data_length, "FirstBurstLength", value))                    return 0;                iscsi_sprintf(value, "%d", session->DefaultTime2Wait);                if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Wait", value))                    return 0;                                iscsi_sprintf(value, "%d", session->DefaultTime2Retain);                if (!iscsi_add_text(session, pdu, data, max_data_length, "DefaultTime2Retain", value))                    return 0;                /* these we must have */                if (!iscsi_add_text(session, pdu, data, max_data_length, "HeaderDigest", "None"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "DataDigest", "None"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxOutstandingR2T", "1"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "MaxConnections", "1"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "ErrorRecoveryLevel", "0"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "IFMarker", "No"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "OFMarker", "No"))                    return 0;                /* FIXME: the caller may want different settings for these. */                if (!iscsi_add_text(session, pdu, data, max_data_length, "DataPDUInOrder", "Yes"))                    return 0;                if (!iscsi_add_text(session, pdu, data, max_data_length, "DataSequenceInOrder", "Yes"))                    return 0;                /* vendor-specific protocol specification. list of protocol level strings in order of preference                  * allowable values are: draft<n> (e.g. draft8), rfc<n> (e.g. rfc666).                 * For example:                  *      "X-com.cisco.protocol=draft16,draft8" requests draft 16, or 8 if 16 isn't supported.                 *      "X-com.cisco.protocol=draft8,draft16" requests draft 8, or 16 if 8 isn't supported.                 *                 * Targets that understand this key SHOULD return the protocol level they selected as                 * a response to this key, though the active_version may be sufficient to distinguish                 * which protocol was chosen.                 *                 * Note: This probably won't work unless we start in op param phase, since the security                  * phase limits what keys we can send, and we'd need to have sent this on the first PDU                 * of the login.  Keep sending it for informational use, and so that we can sanity                 * check things later if the RFC and draft16 are using the same active version number.                 */                if (!iscsi_add_text(session, pdu, data, max_data_length, "X-com.cisco.protocol", "draft16"))                    return 0;            }            else {                /* FIXME: echo back the keys the target sent us, with the current values for those keys                 * or NotUnderstood, and request the next phase.                 * FIXME: make this code handle vendor-defined keys sent by the target.                 * We can't handle them now because we don't have anyplace to save the key until the                  * response is generated, which is what we'd need to do to send key=NotUnderstood.                 */                /* try to go to full feature phase */                login_pdu->curr = session->current_phase;                login_pdu->next = ISCSI_FULL_FEATURE_PHASE;                login_pdu->tbit = 1;            }            break;        }        case ISCSI_SECURITY_NEGOTIATION_PHASE: {            int keytype = iscsiAuthKeyTypeNone;            int rc = iscsiAuthClientSendTransitBit(session->auth_client, &tbit);            /* see if we're ready for a phase change */            if (rc == iscsiAuthStatusNoError) {                login_pdu->tbit = tbit;                if (tbit)                    /* for discovery sessions, try to go right to full feature phase, not op param phase */                    if (session->type == ISCSI_SESSION_TYPE_DISCOVERY)                        login_pdu->next = session->next_phase = ISCSI_FULL_FEATURE_PHASE;                    else                        login_pdu->next = session->next_phase = ISCSI_OP_PARMS_NEGOTIATION_PHASE;                else                    session->next_phase = ISCSI_SECURITY_NEGOTIATION_PHASE;            }            else                return 0;                        /* enumerate all the keys the auth code might want to send */            while (iscsiAuthClientGetNextKeyType(&keytype) == iscsiAuthStatusNoError) {                int present = 0;                char *key = (char *)iscsiAuthClientGetKeyName(keytype);                                /* add the key/value pairs the auth code wants to send */                rc = iscsiAuthClientSendKeyValue(session->auth_client, keytype, &present, value);                if ((rc == iscsiAuthStatusNoError) && present) {                    if (!iscsi_add_text(session, pdu, data, max_data_length, key, value))                        return 0;                }            }            break;        }        case ISCSI_FULL_FEATURE_PHASE:            logmsg(AS_ERROR, "can't send login PDUs in full feature phase\n");            return 0;        default:            logmsg(AS_ERROR, "can't send login PDUs in unknown phase %d\n", session->current_phase);            return 0;    }        return 1;}/* attempt to login to the target. * The caller must check the status class to determine if the login succeeded. * A return of 1 does not mean the login succeeded, it just means this function * worked, and the status class is valid info.  This allows the caller to decide * whether or not to retry logins, so that we don't have any policy logic here. */int iscsi_login(iscsi_session_t *session, char *buffer, size_t bufsize, uint8_t *status_class, uint8_t *status_detail){    int received_pdu = 0;    int ret = 0;        /* prepare the session */    session->CmdSn = 1;    session->ExpCmdSn = 1;    session->MaxCmdSn = 1;    session->ExpStatSn = 0;    session->current_phase = ISCSI_INITIAL_LOGIN_PHASE;    session->partial_response = 0;        if (session->auth_client) {        /* prepare for authentication */        if (iscsiAuthClientInit(session->auth_client, iscsiAuthNodeTypeInitiator) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't init auth_client %p for session %p\n", session->auth_client, session);            return 0;        }        if (iscsiAuthClientSetVersion(session->auth_client, iscsiAuthVersionRfc) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't set auth version RFC for session %p\n", session);            goto done;        }        if (iscsiAuthClientSetUsername(session->auth_client, session->username) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't set username for session %p\n", session);            goto done;        }        if (iscsiAuthClientSetPassword(session->auth_client, session->password, session->password_length) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't set password for session %p\n", session);            goto done;        }        /* FIXME: disable the minimum size check for now */        if (iscsiAuthClientSetIpSec(session->auth_client, 1) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't set password for session %p\n", session);            goto done;        }                if (iscsiAuthClientSetAuthRemote(session->auth_client, 0) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "couldn't set auth remote for session %p\n", session);            goto done;        }    }    /* exchange PDUs until the login phase is complete, or an error occurs */    do {        struct IscsiHdr pdu;        struct IscsiLoginRspHdr *login_rsp_pdu = (struct IscsiLoginRspHdr *)&pdu;        char *data;        int max_data_length;        int timeout = 0;        memset(buffer, 0, bufsize);        data = buffer;        max_data_length = bufsize;        /* pick the appropriate timeout. If we know the target has         * responded before, and we're in the security phase, we use a         * longer timeout, since the authentication alogorithms can         * take a while, especially if the target has to go talk to a         * tacacs or RADIUS server (which may or may not be         * responding).         */        if (received_pdu && (session->current_phase == ISCSI_SECURITY_NEGOTIATION_PHASE))            timeout = session->auth_timeout;        else            timeout = session->login_timeout;        /* fill in the PDU header and text data based on the login phase that we're in */        if (!iscsi_make_login_pdu(session, &pdu, data, max_data_length))            goto done;        /* send a PDU to the target */        if (!iscsi_send_pdu(session, &pdu, data, timeout))            goto done;                /* read the target's response into the same buffer */        memset(buffer, 0, bufsize);        if (!iscsi_recv_pdu(session, &pdu, sizeof(pdu), data, max_data_length, timeout))            goto done;        received_pdu = 1;        /* check the PDU response type */        if (pdu.opcode == (ISCSI_OP_LOGIN_RSP | 0xC0)) {            /* it's a draft 8 login response, which we can't deal with */            logmsg(AS_ERROR, "received iSCSI draft 8 login response opcode 0x%x, expected draft 16 login response 0x%2x\n",                   pdu.opcode, ISCSI_OP_LOGIN_RSP);            logmsg(AS_ERROR, "please make sure that you have installed the correct driver version.\n");            goto done;        }        else if (pdu.opcode != ISCSI_OP_LOGIN_RSP) {            logmsg(AS_ERROR, "received opcode 0x%2x during login, expected login response 0x%2x\n",                   pdu.opcode, ISCSI_OP_LOGIN_RSP);            goto done;        }        /* give the caller the status class and detail from the last login response PDU received */        if (status_class)            *status_class = login_rsp_pdu->status_class;        if (status_detail)            *status_detail = login_rsp_pdu->status_detail;        if (login_rsp_pdu->status_class != STATUS_CLASS_SUCCESS) {            /* this code didn't fail, but the login did.               * The caller must check the class and detail.             * We process the login response anyway, so that             * redirects can reset the session's IP address.             */            ret = 1;             iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length);            goto done;        }        else if (!iscsi_process_login_response(session, login_rsp_pdu, data, max_data_length))            goto done;    } while (session->current_phase != ISCSI_FULL_FEATURE_PHASE);    ret = 1; done:    if (session->auth_client) {        if (iscsiAuthClientFinish(session->auth_client) != iscsiAuthStatusNoError) {            logmsg(AS_ERROR, "error finishing authclient\n");            return 0;        }    }    return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -