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

📄 iscsi-login.c

📁 ISCSI user client software.Client would be used to access the IPSAN server.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * iSCSI login library * Copyright (C) 2001 Cisco Systems, Inc. * maintained by linux-iscsi-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * See the file COPYING included with this distribution for more details. * * $Id: iscsi-login.c,v 1.33 2005/01/19 22:55:30 mikenc Exp $ * * * Formation of iSCSI login pdu, processing the login response and other * functions are defined here */#include "iscsi-session.h"#include "iscsi-login.h"#include "iscsi-protocol.h"#include "iscsi-sfnet.h"/* caller is assumed to be well-behaved and passing NUL terminated strings */intiscsi_add_text(struct iscsi_session *session, struct iscsi_hdr *pdu, char *data,	       int max_data_length, char *param, char *value){	int param_len = strlen(param);	int value_len = strlen(value);	int length = param_len + 1 + value_len + 1;	/* param, separator,							 * value, and trailing							 * NULL							 */	int pdu_length = ntoh24(pdu->dlength);	char *text = data;	char *end = data + max_data_length;	char *pdu_text;	/* find the end of the current text */	text += pdu_length;	pdu_text = text;	pdu_length += length;	if (text + length >= end) {		iscsi_host_notice(session, "Failed to add login text "				  "'%s=%s'\n", param, value);		return 0;	}	/* param */	strncpy(text, param, param_len);	text += param_len;	/* separator */	*text++ = ISCSI_TEXT_SEPARATOR;	/* value */	strncpy(text, value, value_len);	text += value_len;	/* NUL */	*text++ = '\0';	/* update the length in the PDU header */	hton24(pdu->dlength, pdu_length);	return 1;}static intiscsi_find_key_value(char *param, char *pdu, char *pdu_end, char **value_start,		     char **value_end){	char *str = param;	char *text = pdu;	char *value;	if (value_start)		*value_start = NULL;	if (value_end)		*value_end = NULL;	/* make sure they contain the same bytes */	while (*str) {		if (text >= pdu_end)			return 0;		if (*text == '\0')			return 0;		if (*str != *text)			return 0;		str++;		text++;	}	if ((text >= pdu_end) || (*text == '\0')	    || (*text != ISCSI_TEXT_SEPARATOR)) {		return 0;	}	/* find the value */	value = text + 1;	/* find the end of the value */	while ((text < pdu_end) && (*text))		text++;	if (value_start)		*value_start = value;	if (value_end)		*value_end = text;	return 1;}static enum iscsi_login_statusget_auth_key_type(struct iscsi_acl *auth_client, char **data, char *end){	char *key;	char *value = NULL;        char *value_end = NULL;	char *text = *data;	int keytype = AUTH_KEY_TYPE_NONE;	while (acl_get_next_key_type(&keytype) == AUTH_STATUS_NO_ERROR) {		key = (char *)acl_get_key_name(keytype);		if (key && iscsi_find_key_value(key, text, end, &value,						&value_end)) {			if (acl_recv_key_value(auth_client, keytype, value) !=					       AUTH_STATUS_NO_ERROR) {				iscsi_err("login negotiation failed, can't "					  "accept %s in security stage\n",					  text);				return LOGIN_NEGOTIATION_FAILED;			}			text = value_end;			*data = text;			return LOGIN_OK;		}	}	iscsi_err("Login negotiation failed, can't accept %s in security "		  "stage\n", text);	return LOGIN_NEGOTIATION_FAILED;}static enum iscsi_login_statusget_security_text_keys(struct iscsi_session *session, char **data,		       struct iscsi_acl *auth_client, char *end){	char *text = *data;	char *value = NULL;	char *value_end = NULL;	size_t size;	int tag;	enum iscsi_login_status ret;	/*	 * a few keys are possible in Security stage	 * which the auth code doesn't care about, but	 * which we might want to see, or at least not	 * choke on.	 */	if (iscsi_find_key_value("TargetAlias", text, end, &value,		&value_end)) {		size = value_end - value;		session->target_alias = kmalloc(size + 1, GFP_ATOMIC);		if (!session->target_alias) {			/* Alias not critical. So just print an error */			iscsi_host_err(session, "Login failed to allocate "				       "alias\n");			*data = value_end;			return LOGIN_OK;		}		memcpy(session->target_alias, value, size);		session->target_alias[size] = '\0';		text = value_end;	} else if (iscsi_find_key_value("TargetAddress", text, end, &value,					 &value_end)) {		/*		 * if possible, change the session's		 * ip_address and port to the new		 * TargetAddress		 */		if (iscsi_update_address(session, value)) {			text = value_end;		} else {			iscsi_host_err(session, "Login redirection failed, "				       "can't handle redirection to %s\n",				       value);			return LOGIN_REDIRECTION_FAILED;		}	} 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		 */		tag = simple_strtoul(value, NULL, 0);		if (session->portal_group_tag >= 0) {			if (tag != session->portal_group_tag) {				iscsi_host_err(session, "Portal group tag "					       "mismatch, expected %u, "					       "received %u\n",					       session->portal_group_tag, tag);				return LOGIN_WRONG_PORTAL_GROUP;			}		} else			/* we now know the tag */			session->portal_group_tag = tag;		text = value_end;	} else {		/*		 * any key we don't recognize either		 * goes to the auth code, or we choke		 * on it		 */		ret = get_auth_key_type(auth_client, &text, end);		if (ret != LOGIN_OK)			return ret;	}	*data = text;	return LOGIN_OK;}static enum iscsi_login_statusget_op_params_text_keys(struct iscsi_session *session, char **data, char *end){	char *text = *data;	char *value = NULL;	char *value_end = NULL;	size_t size;	if (iscsi_find_key_value("TargetAlias", text, end, &value,				 &value_end)) {		size = value_end - value;		if (session->target_alias &&		    strlen(session->target_alias) == size &&		    memcmp(session->target_alias, value, size) == 0) {			*data = value_end;			return LOGIN_OK;		}		kfree(session->target_alias);		session->target_alias = kmalloc(size + 1, GFP_ATOMIC);		if (!session->target_alias) {			/* Alias not critical. So just print an error */			iscsi_host_err(session, "Login failed to allocate "				       "alias\n");			*data = value_end;			return LOGIN_OK;		}		memcpy(session->target_alias, value, size);		session->target_alias[size] = '\0';		text = value_end;	} else if (iscsi_find_key_value("TargetAddress", text, end, &value,					 &value_end)) {		if (iscsi_update_address(session, value))			text = value_end;		else {			iscsi_host_err(session, "Login redirection failed, "				       "can't handle redirection to %s\n",				       value);			return LOGIN_REDIRECTION_FAILED;		}	} else if (iscsi_find_key_value("TargetPortalGroupTag", text, end,					 &value, &value_end)) {		/*		 * confirm we reached the portal group we were expecting to		 */		int tag = simple_strtoul(value, NULL, 0);		if (session->portal_group_tag >= 0) {			if (tag != session->portal_group_tag) {				iscsi_host_err(session, "Portal group tag "					       "mismatch, expected %u, "					       "received %u\n",					       session->portal_group_tag, tag);				return LOGIN_WRONG_PORTAL_GROUP;			}		} 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 (session->type == ISCSI_SESSION_TYPE_NORMAL) {			if (value && (strcmp(value, "Yes") == 0))				session->initial_r2t = 1;			else				session->initial_r2t = 0;		} else			session->irrelevant_keys_bitmap |=						IRRELEVANT_INITIALR2T;		text = value_end;	} else if (iscsi_find_key_value("ImmediateData", text, end, &value,					 &value_end)) {		if (session->type == ISCSI_SESSION_TYPE_NORMAL) {			if (value && (strcmp(value, "Yes") == 0))				session->immediate_data = 1;			else				session->immediate_data = 0;		} else			session->irrelevant_keys_bitmap |=						IRRELEVANT_IMMEDIATEDATA;		text = value_end;	} else if (iscsi_find_key_value("MaxRecvDataSegmentLength", text, end,				     &value, &value_end)) {		session->max_xmit_data_segment_len =					    simple_strtoul(value, NULL, 0);		text = value_end;	} else if (iscsi_find_key_value("FirstBurstLength", text, end, &value,					 &value_end)) {		if (session->type == ISCSI_SESSION_TYPE_NORMAL)			session->first_burst_len =					    	simple_strtoul(value, NULL, 0);		else			session->irrelevant_keys_bitmap |=						IRRELEVANT_FIRSTBURSTLENGTH;		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		 */		if (session->type == ISCSI_SESSION_TYPE_NORMAL)			session->max_burst_len = simple_strtoul(value, NULL, 0);		else			session->irrelevant_keys_bitmap |=						IRRELEVANT_MAXBURSTLENGTH;		text = value_end;	} else if (iscsi_find_key_value("HeaderDigest", text, end, &value,					 &value_end)) {		if (strcmp(value, "None") == 0) {			if (session->header_digest != ISCSI_DIGEST_CRC32C)				session->header_digest = ISCSI_DIGEST_NONE;			else {				iscsi_host_err(session, "Login negotiation "					       "failed, HeaderDigest=CRC32C "					       "is required, can't accept "					       "%s\n", text);				return LOGIN_NEGOTIATION_FAILED;			}		} else if (strcmp(value, "CRC32C") == 0) {			if (session->header_digest != ISCSI_DIGEST_NONE)				session->header_digest = ISCSI_DIGEST_CRC32C;			else {				iscsi_host_err(session, "Login negotiation "					       "failed, HeaderDigest=None is "					       "required, can't accept %s\n",					       text);				return LOGIN_NEGOTIATION_FAILED;			}		} else {			iscsi_host_err(session, "Login negotiation failed, "				       "can't accept %s\n", text);			return LOGIN_NEGOTIATION_FAILED;		}		text = value_end;	} else if (iscsi_find_key_value("DataDigest", text, end, &value,					 &value_end)) {		if (strcmp(value, "None") == 0) {			if (session->data_digest != ISCSI_DIGEST_CRC32C)				session->data_digest = ISCSI_DIGEST_NONE;			else {				iscsi_host_err(session, "Login negotiation "					       "failed, DataDigest=CRC32C "					       "is required, can't accept "					       "%s\n", text);				return LOGIN_NEGOTIATION_FAILED;			}		} else if (strcmp(value, "CRC32C") == 0) {			if (session->data_digest != ISCSI_DIGEST_NONE)				session->data_digest = ISCSI_DIGEST_CRC32C;			else {				iscsi_host_err(session, "Login negotiation "					       "failed, DataDigest=None is "					       "required, can't accept %s\n",					       text);				return LOGIN_NEGOTIATION_FAILED;			}		} else {			iscsi_host_err(session, "Login negotiation failed, "				       "can't accept %s\n", text);			return LOGIN_NEGOTIATION_FAILED;		}		text = value_end;	} else if (iscsi_find_key_value("DefaultTime2Wait", text, end, &value,					 &value_end)) {		session->def_time2wait = simple_strtoul(value, NULL, 0);		text = value_end;	} else if (iscsi_find_key_value("DefaultTime2Retain", text, end,					 &value, &value_end)) {		session->def_time2retain = simple_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 (session->type == ISCSI_SESSION_TYPE_NORMAL) {			if (value && strcmp(value, "Yes") == 0)				session->data_pdu_in_order = 1;			else				session->data_pdu_in_order = 0;		} else			session->irrelevant_keys_bitmap |=						IRRELEVANT_DATAPDUINORDER;		text = value_end;	} else if (iscsi_find_key_value ("DataSequenceInOrder", text, end,					 &value, &value_end)) {		if (session->type == ISCSI_SESSION_TYPE_NORMAL)			if (value && strcmp(value, "Yes") == 0)				session->data_seq_in_order = 1;			else				session->data_seq_in_order = 0;		else			session->irrelevant_keys_bitmap |=						IRRELEVANT_DATASEQUENCEINORDER;		text = value_end;	} else if (iscsi_find_key_value("MaxOutstandingR2T", text, end, &value,					 &value_end)) {		if (session->type == ISCSI_SESSION_TYPE_NORMAL) {			if (strcmp(value, "1")) {				iscsi_host_err(session, "Login negotiation "					       "failed, can't accept Max"					       "OutstandingR2T %s\n", value);				return LOGIN_NEGOTIATION_FAILED;			}		} else			session->irrelevant_keys_bitmap |=						IRRELEVANT_MAXOUTSTANDINGR2T;		text = value_end;	} else if (iscsi_find_key_value("MaxConnections", text, end, &value,					 &value_end)) {		if (session->type == ISCSI_SESSION_TYPE_NORMAL) {			if (strcmp(value, "1")) {				iscsi_host_err(session, "Login negotiation "					       "failed, can't accept Max"					       "Connections %s\n", value);				return LOGIN_NEGOTIATION_FAILED;			}

⌨️ 快捷键说明

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