iscsi-target: remove support for obsolete markers
Support for markers is currently broken because of a bug in iscsi_enforce_integrity_rules(): the "IFMarkInt_Reject" and "OFMarkInt_Reject" variables are always equal to 1 in iscsi_enforce_integrity_rules(). Moreover, fixed interval markers keys (IFMarker, OFMarker, IFMarkInt and OFMarkInt) are obsolete according to iSCSI RFC 7143: >From http://tools.ietf.org/html/rfc7143#section-13.25: 13.25. Obsoleted Keys This document obsoletes the following keys defined in [RFC3720]: IFMarker, OFMarker, OFMarkInt, and IFMarkInt. However, iSCSI implementations compliant to this document may still receive these obsoleted keys -- i.e., in a responder role -- in a text negotiation. When an IFMarker or OFMarker key is received, a compliant iSCSI implementation SHOULD respond with the constant "Reject" value. The implementation MAY alternatively respond with a "No" value. However, the implementation MUST NOT respond with a "NotUnderstood" value for either of these keys. When an IFMarkInt or OFMarkInt key is received, a compliant iSCSI implementation MUST respond with the constant "Reject" value. The implementation MUST NOT respond with a "NotUnderstood" value for either of these keys. This patch disables markers by turning the corresponding parameters to read-only. The default value of IFMarker and OFMarker remains "No" but the user cannot change it to "Yes" anymore. The new value of IFMarkInt and OFMarkInt is "Reject". (Drop left-over iscsi_get_value_from_number_range + make configfs parameters attrs R/W nops - nab) Signed-off-by: Christophe Vu-Brugier <cvubrugier@fastmail.fm> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Родитель
414e462727
Коммит
c04a6091c9
|
@ -2736,11 +2736,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
cmd->iov_data_count = iov_count;
|
cmd->iov_data_count = iov_count;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
/* sendpage is preferred but can't insert markers */
|
|
||||||
if (!conn->conn_ops->IFMarker)
|
|
||||||
ret = iscsit_fe_sendpage_sg(cmd, conn);
|
ret = iscsit_fe_sendpage_sg(cmd, conn);
|
||||||
else
|
|
||||||
ret = iscsit_send_tx_data(cmd, conn, 0);
|
|
||||||
|
|
||||||
iscsit_unmap_iovec(cmd);
|
iscsit_unmap_iovec(cmd);
|
||||||
|
|
||||||
|
@ -4072,17 +4068,9 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
|
||||||
" opcode while ERL=0, closing iSCSI connection.\n");
|
" opcode while ERL=0, closing iSCSI connection.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!conn->conn_ops->OFMarker) {
|
pr_err("Unable to recover from unknown opcode while OFMarker=No,"
|
||||||
pr_err("Unable to recover from unknown"
|
" closing iSCSI connection.\n");
|
||||||
" opcode while OFMarker=No, closing iSCSI"
|
ret = -1;
|
||||||
" connection.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (iscsit_recover_from_unknown_opcode(conn) < 0) {
|
|
||||||
pr_err("Unable to recover from unknown"
|
|
||||||
" opcode, closing iSCSI connection.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -956,56 +956,3 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
||||||
|
|
||||||
iscsit_handle_connection_cleanup(conn);
|
iscsit_handle_connection_cleanup(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the simple function that makes the magic of
|
|
||||||
* sync and steering happen in the follow paradoxical order:
|
|
||||||
*
|
|
||||||
* 0) Receive conn->of_marker (bytes left until next OFMarker)
|
|
||||||
* bytes into an offload buffer. When we pass the exact number
|
|
||||||
* of bytes in conn->of_marker, iscsit_dump_data_payload() and hence
|
|
||||||
* rx_data() will automatically receive the identical u32 marker
|
|
||||||
* values and store it in conn->of_marker_offset;
|
|
||||||
* 1) Now conn->of_marker_offset will contain the offset to the start
|
|
||||||
* of the next iSCSI PDU. Dump these remaining bytes into another
|
|
||||||
* offload buffer.
|
|
||||||
* 2) We are done!
|
|
||||||
* Next byte in the TCP stream will contain the next iSCSI PDU!
|
|
||||||
* Cool Huh?!
|
|
||||||
*/
|
|
||||||
int iscsit_recover_from_unknown_opcode(struct iscsi_conn *conn)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Make sure the remaining bytes to next maker is a sane value.
|
|
||||||
*/
|
|
||||||
if (conn->of_marker > (conn->conn_ops->OFMarkInt * 4)) {
|
|
||||||
pr_err("Remaining bytes to OFMarker: %u exceeds"
|
|
||||||
" OFMarkInt bytes: %u.\n", conn->of_marker,
|
|
||||||
conn->conn_ops->OFMarkInt * 4);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("Advancing %u bytes in TCP stream to get to the"
|
|
||||||
" next OFMarker.\n", conn->of_marker);
|
|
||||||
|
|
||||||
if (iscsit_dump_data_payload(conn, conn->of_marker, 0) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the offset marker we retrived is a valid value.
|
|
||||||
*/
|
|
||||||
if (conn->of_marker_offset > (ISCSI_HDR_LEN + (ISCSI_CRC_LEN * 2) +
|
|
||||||
conn->conn_ops->MaxRecvDataSegmentLength)) {
|
|
||||||
pr_err("OfMarker offset value: %u exceeds limit.\n",
|
|
||||||
conn->of_marker_offset);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("Discarding %u bytes of TCP stream to get to the"
|
|
||||||
" next iSCSI Opcode.\n", conn->of_marker_offset);
|
|
||||||
|
|
||||||
if (iscsit_dump_data_payload(conn, conn->of_marker_offset, 0) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,6 +10,5 @@ extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
|
||||||
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
|
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
|
||||||
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
|
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
|
||||||
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
|
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
|
||||||
extern int iscsit_recover_from_unknown_opcode(struct iscsi_conn *);
|
|
||||||
|
|
||||||
#endif /*** ISCSI_TARGET_ERL0_H ***/
|
#endif /*** ISCSI_TARGET_ERL0_H ***/
|
||||||
|
|
|
@ -410,8 +410,6 @@ static int iscsi_login_zero_tsih_s2(
|
||||||
if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl))
|
if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
|
|
||||||
return -1;
|
|
||||||
/*
|
/*
|
||||||
* Set RDMAExtensions=Yes by default for iSER enabled network portals
|
* Set RDMAExtensions=Yes by default for iSER enabled network portals
|
||||||
*/
|
*/
|
||||||
|
@ -477,59 +475,6 @@ check_prot:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove PSTATE_NEGOTIATE for the four FIM related keys.
|
|
||||||
* The Initiator node will be able to enable FIM by proposing them itself.
|
|
||||||
*/
|
|
||||||
int iscsi_login_disable_FIM_keys(
|
|
||||||
struct iscsi_param_list *param_list,
|
|
||||||
struct iscsi_conn *conn)
|
|
||||||
{
|
|
||||||
struct iscsi_param *param;
|
|
||||||
|
|
||||||
param = iscsi_find_param_from_key("OFMarker", param_list);
|
|
||||||
if (!param) {
|
|
||||||
pr_err("iscsi_find_param_from_key() for"
|
|
||||||
" OFMarker failed\n");
|
|
||||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
|
||||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
|
|
||||||
param = iscsi_find_param_from_key("OFMarkInt", param_list);
|
|
||||||
if (!param) {
|
|
||||||
pr_err("iscsi_find_param_from_key() for"
|
|
||||||
" IFMarker failed\n");
|
|
||||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
|
||||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
|
|
||||||
param = iscsi_find_param_from_key("IFMarker", param_list);
|
|
||||||
if (!param) {
|
|
||||||
pr_err("iscsi_find_param_from_key() for"
|
|
||||||
" IFMarker failed\n");
|
|
||||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
|
||||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
|
|
||||||
param = iscsi_find_param_from_key("IFMarkInt", param_list);
|
|
||||||
if (!param) {
|
|
||||||
pr_err("iscsi_find_param_from_key() for"
|
|
||||||
" IFMarker failed\n");
|
|
||||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
|
||||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iscsi_login_non_zero_tsih_s1(
|
static int iscsi_login_non_zero_tsih_s1(
|
||||||
struct iscsi_conn *conn,
|
struct iscsi_conn *conn,
|
||||||
unsigned char *buf)
|
unsigned char *buf)
|
||||||
|
@ -616,7 +561,7 @@ static int iscsi_login_non_zero_tsih_s2(
|
||||||
if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt))
|
if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return iscsi_login_disable_FIM_keys(conn->param_list, conn);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iscsi_login_post_auth_non_zero_tsih(
|
int iscsi_login_post_auth_non_zero_tsih(
|
||||||
|
@ -765,7 +710,6 @@ int iscsi_post_login_handler(
|
||||||
conn->conn_state = TARG_CONN_STATE_LOGGED_IN;
|
conn->conn_state = TARG_CONN_STATE_LOGGED_IN;
|
||||||
|
|
||||||
iscsi_set_connection_parameters(conn->conn_ops, conn->param_list);
|
iscsi_set_connection_parameters(conn->conn_ops, conn->param_list);
|
||||||
iscsit_set_sync_and_steering_values(conn);
|
|
||||||
/*
|
/*
|
||||||
* SCSI Initiator -> SCSI Target Port Mapping
|
* SCSI Initiator -> SCSI Target Port Mapping
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,5 @@ extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
|
||||||
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
|
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
|
||||||
bool, bool);
|
bool, bool);
|
||||||
extern int iscsi_target_login_thread(void *);
|
extern int iscsi_target_login_thread(void *);
|
||||||
extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
|
|
||||||
|
|
||||||
#endif /*** ISCSI_TARGET_LOGIN_H ***/
|
#endif /*** ISCSI_TARGET_LOGIN_H ***/
|
||||||
|
|
|
@ -34,13 +34,6 @@ int iscsi_login_rx_data(
|
||||||
iov.iov_len = length;
|
iov.iov_len = length;
|
||||||
iov.iov_base = buf;
|
iov.iov_base = buf;
|
||||||
|
|
||||||
/*
|
|
||||||
* Initial Marker-less Interval.
|
|
||||||
* Add the values regardless of IFMarker/OFMarker, considering
|
|
||||||
* it may not be negoitated yet.
|
|
||||||
*/
|
|
||||||
conn->of_marker += length;
|
|
||||||
|
|
||||||
rx_got = rx_data(conn, &iov, 1, length);
|
rx_got = rx_data(conn, &iov, 1, length);
|
||||||
if (rx_got != length) {
|
if (rx_got != length) {
|
||||||
pr_err("rx_data returned %d, expecting %d.\n",
|
pr_err("rx_data returned %d, expecting %d.\n",
|
||||||
|
@ -72,13 +65,6 @@ int iscsi_login_tx_data(
|
||||||
iov_cnt++;
|
iov_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Initial Marker-less Interval.
|
|
||||||
* Add the values regardless of IFMarker/OFMarker, considering
|
|
||||||
* it may not be negoitated yet.
|
|
||||||
*/
|
|
||||||
conn->if_marker += length;
|
|
||||||
|
|
||||||
tx_sent = tx_data(conn, &iov[0], iov_cnt, length);
|
tx_sent = tx_data(conn, &iov[0], iov_cnt, length);
|
||||||
if (tx_sent != length) {
|
if (tx_sent != length) {
|
||||||
pr_err("tx_data returned %d, expecting %d.\n",
|
pr_err("tx_data returned %d, expecting %d.\n",
|
||||||
|
@ -97,12 +83,6 @@ void iscsi_dump_conn_ops(struct iscsi_conn_ops *conn_ops)
|
||||||
"CRC32C" : "None");
|
"CRC32C" : "None");
|
||||||
pr_debug("MaxRecvDataSegmentLength: %u\n",
|
pr_debug("MaxRecvDataSegmentLength: %u\n",
|
||||||
conn_ops->MaxRecvDataSegmentLength);
|
conn_ops->MaxRecvDataSegmentLength);
|
||||||
pr_debug("OFMarker: %s\n", (conn_ops->OFMarker) ? "Yes" : "No");
|
|
||||||
pr_debug("IFMarker: %s\n", (conn_ops->IFMarker) ? "Yes" : "No");
|
|
||||||
if (conn_ops->OFMarker)
|
|
||||||
pr_debug("OFMarkInt: %u\n", conn_ops->OFMarkInt);
|
|
||||||
if (conn_ops->IFMarker)
|
|
||||||
pr_debug("IFMarkInt: %u\n", conn_ops->IFMarkInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops)
|
void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops)
|
||||||
|
@ -194,10 +174,6 @@ static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *para
|
||||||
case TYPERANGE_DIGEST:
|
case TYPERANGE_DIGEST:
|
||||||
param->type = TYPE_VALUE_LIST | TYPE_STRING;
|
param->type = TYPE_VALUE_LIST | TYPE_STRING;
|
||||||
break;
|
break;
|
||||||
case TYPERANGE_MARKINT:
|
|
||||||
param->type = TYPE_NUMBER_RANGE;
|
|
||||||
param->type_range |= TYPERANGE_1_TO_65535;
|
|
||||||
break;
|
|
||||||
case TYPERANGE_ISCSINAME:
|
case TYPERANGE_ISCSINAME:
|
||||||
case TYPERANGE_SESSIONTYPE:
|
case TYPERANGE_SESSIONTYPE:
|
||||||
case TYPERANGE_TARGETADDRESS:
|
case TYPERANGE_TARGETADDRESS:
|
||||||
|
@ -422,13 +398,13 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
|
||||||
|
|
||||||
param = iscsi_set_default_param(pl, IFMARKINT, INITIAL_IFMARKINT,
|
param = iscsi_set_default_param(pl, IFMARKINT, INITIAL_IFMARKINT,
|
||||||
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
|
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
|
||||||
TYPERANGE_MARKINT, USE_INITIAL_ONLY);
|
TYPERANGE_UTF8, USE_INITIAL_ONLY);
|
||||||
if (!param)
|
if (!param)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
param = iscsi_set_default_param(pl, OFMARKINT, INITIAL_OFMARKINT,
|
param = iscsi_set_default_param(pl, OFMARKINT, INITIAL_OFMARKINT,
|
||||||
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
|
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
|
||||||
TYPERANGE_MARKINT, USE_INITIAL_ONLY);
|
TYPERANGE_UTF8, USE_INITIAL_ONLY);
|
||||||
if (!param)
|
if (!param)
|
||||||
goto out;
|
goto out;
|
||||||
/*
|
/*
|
||||||
|
@ -524,9 +500,9 @@ int iscsi_set_keys_to_negotiate(
|
||||||
} else if (!strcmp(param->name, OFMARKER)) {
|
} else if (!strcmp(param->name, OFMARKER)) {
|
||||||
SET_PSTATE_NEGOTIATE(param);
|
SET_PSTATE_NEGOTIATE(param);
|
||||||
} else if (!strcmp(param->name, IFMARKINT)) {
|
} else if (!strcmp(param->name, IFMARKINT)) {
|
||||||
SET_PSTATE_NEGOTIATE(param);
|
SET_PSTATE_REJECT(param);
|
||||||
} else if (!strcmp(param->name, OFMARKINT)) {
|
} else if (!strcmp(param->name, OFMARKINT)) {
|
||||||
SET_PSTATE_NEGOTIATE(param);
|
SET_PSTATE_REJECT(param);
|
||||||
} else if (!strcmp(param->name, RDMAEXTENSIONS)) {
|
} else if (!strcmp(param->name, RDMAEXTENSIONS)) {
|
||||||
if (iser)
|
if (iser)
|
||||||
SET_PSTATE_NEGOTIATE(param);
|
SET_PSTATE_NEGOTIATE(param);
|
||||||
|
@ -906,91 +882,6 @@ static int iscsi_check_numerical_value(struct iscsi_param *param, char *value_pt
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsi_check_numerical_range_value(struct iscsi_param *param, char *value)
|
|
||||||
{
|
|
||||||
char *left_val_ptr = NULL, *right_val_ptr = NULL;
|
|
||||||
char *tilde_ptr = NULL;
|
|
||||||
u32 left_val, right_val, local_left_val;
|
|
||||||
|
|
||||||
if (strcmp(param->name, IFMARKINT) &&
|
|
||||||
strcmp(param->name, OFMARKINT)) {
|
|
||||||
pr_err("Only parameters \"%s\" or \"%s\" may contain a"
|
|
||||||
" numerical range value.\n", IFMARKINT, OFMARKINT);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_PSTATE_PROPOSER(param))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tilde_ptr = strchr(value, '~');
|
|
||||||
if (!tilde_ptr) {
|
|
||||||
pr_err("Unable to locate numerical range indicator"
|
|
||||||
" \"~\" for \"%s\".\n", param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*tilde_ptr = '\0';
|
|
||||||
|
|
||||||
left_val_ptr = value;
|
|
||||||
right_val_ptr = value + strlen(left_val_ptr) + 1;
|
|
||||||
|
|
||||||
if (iscsi_check_numerical_value(param, left_val_ptr) < 0)
|
|
||||||
return -1;
|
|
||||||
if (iscsi_check_numerical_value(param, right_val_ptr) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
left_val = simple_strtoul(left_val_ptr, NULL, 0);
|
|
||||||
right_val = simple_strtoul(right_val_ptr, NULL, 0);
|
|
||||||
*tilde_ptr = '~';
|
|
||||||
|
|
||||||
if (right_val < left_val) {
|
|
||||||
pr_err("Numerical range for parameter \"%s\" contains"
|
|
||||||
" a right value which is less than the left.\n",
|
|
||||||
param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For now, enforce reasonable defaults for [I,O]FMarkInt.
|
|
||||||
*/
|
|
||||||
tilde_ptr = strchr(param->value, '~');
|
|
||||||
if (!tilde_ptr) {
|
|
||||||
pr_err("Unable to locate numerical range indicator"
|
|
||||||
" \"~\" for \"%s\".\n", param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*tilde_ptr = '\0';
|
|
||||||
|
|
||||||
left_val_ptr = param->value;
|
|
||||||
right_val_ptr = param->value + strlen(left_val_ptr) + 1;
|
|
||||||
|
|
||||||
local_left_val = simple_strtoul(left_val_ptr, NULL, 0);
|
|
||||||
*tilde_ptr = '~';
|
|
||||||
|
|
||||||
if (param->set_param) {
|
|
||||||
if ((left_val < local_left_val) ||
|
|
||||||
(right_val < local_left_val)) {
|
|
||||||
pr_err("Passed value range \"%u~%u\" is below"
|
|
||||||
" minimum left value \"%u\" for key \"%s\","
|
|
||||||
" rejecting.\n", left_val, right_val,
|
|
||||||
local_left_val, param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((left_val < local_left_val) &&
|
|
||||||
(right_val < local_left_val)) {
|
|
||||||
pr_err("Received value range \"%u~%u\" is"
|
|
||||||
" below minimum left value \"%u\" for key"
|
|
||||||
" \"%s\", rejecting.\n", left_val, right_val,
|
|
||||||
local_left_val, param->name);
|
|
||||||
SET_PSTATE_REJECT(param);
|
|
||||||
if (iscsi_update_param_value(param, REJECT) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *value)
|
static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *value)
|
||||||
{
|
{
|
||||||
if (IS_PSTATE_PROPOSER(param))
|
if (IS_PSTATE_PROPOSER(param))
|
||||||
|
@ -1027,33 +918,6 @@ static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *val
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is used to pick a value range number, currently just
|
|
||||||
* returns the lesser of both right values.
|
|
||||||
*/
|
|
||||||
static char *iscsi_get_value_from_number_range(
|
|
||||||
struct iscsi_param *param,
|
|
||||||
char *value)
|
|
||||||
{
|
|
||||||
char *end_ptr, *tilde_ptr1 = NULL, *tilde_ptr2 = NULL;
|
|
||||||
u32 acceptor_right_value, proposer_right_value;
|
|
||||||
|
|
||||||
tilde_ptr1 = strchr(value, '~');
|
|
||||||
if (!tilde_ptr1)
|
|
||||||
return NULL;
|
|
||||||
*tilde_ptr1++ = '\0';
|
|
||||||
proposer_right_value = simple_strtoul(tilde_ptr1, &end_ptr, 0);
|
|
||||||
|
|
||||||
tilde_ptr2 = strchr(param->value, '~');
|
|
||||||
if (!tilde_ptr2)
|
|
||||||
return NULL;
|
|
||||||
*tilde_ptr2++ = '\0';
|
|
||||||
acceptor_right_value = simple_strtoul(tilde_ptr2, &end_ptr, 0);
|
|
||||||
|
|
||||||
return (acceptor_right_value >= proposer_right_value) ?
|
|
||||||
tilde_ptr1 : tilde_ptr2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *iscsi_check_valuelist_for_support(
|
static char *iscsi_check_valuelist_for_support(
|
||||||
struct iscsi_param *param,
|
struct iscsi_param *param,
|
||||||
char *value)
|
char *value)
|
||||||
|
@ -1203,14 +1067,6 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
|
||||||
pr_debug("Updated %s to target MXDSL value: %s\n",
|
pr_debug("Updated %s to target MXDSL value: %s\n",
|
||||||
param->name, param->value);
|
param->name, param->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (IS_TYPE_NUMBER_RANGE(param)) {
|
|
||||||
negoitated_value = iscsi_get_value_from_number_range(
|
|
||||||
param, value);
|
|
||||||
if (!negoitated_value)
|
|
||||||
return -1;
|
|
||||||
if (iscsi_update_param_value(param, negoitated_value) < 0)
|
|
||||||
return -1;
|
|
||||||
} else if (IS_TYPE_VALUE_LIST(param)) {
|
} else if (IS_TYPE_VALUE_LIST(param)) {
|
||||||
negoitated_value = iscsi_check_valuelist_for_support(
|
negoitated_value = iscsi_check_valuelist_for_support(
|
||||||
param, value);
|
param, value);
|
||||||
|
@ -1239,47 +1095,7 @@ static int iscsi_check_proposer_state(struct iscsi_param *param, char *value)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_TYPE_NUMBER_RANGE(param)) {
|
if (IS_TYPE_VALUE_LIST(param)) {
|
||||||
u32 left_val = 0, right_val = 0, recieved_value = 0;
|
|
||||||
char *left_val_ptr = NULL, *right_val_ptr = NULL;
|
|
||||||
char *tilde_ptr = NULL;
|
|
||||||
|
|
||||||
if (!strcmp(value, IRRELEVANT) || !strcmp(value, REJECT)) {
|
|
||||||
if (iscsi_update_param_value(param, value) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tilde_ptr = strchr(value, '~');
|
|
||||||
if (tilde_ptr) {
|
|
||||||
pr_err("Illegal \"~\" in response for \"%s\".\n",
|
|
||||||
param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tilde_ptr = strchr(param->value, '~');
|
|
||||||
if (!tilde_ptr) {
|
|
||||||
pr_err("Unable to locate numerical range"
|
|
||||||
" indicator \"~\" for \"%s\".\n", param->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*tilde_ptr = '\0';
|
|
||||||
|
|
||||||
left_val_ptr = param->value;
|
|
||||||
right_val_ptr = param->value + strlen(left_val_ptr) + 1;
|
|
||||||
left_val = simple_strtoul(left_val_ptr, NULL, 0);
|
|
||||||
right_val = simple_strtoul(right_val_ptr, NULL, 0);
|
|
||||||
recieved_value = simple_strtoul(value, NULL, 0);
|
|
||||||
|
|
||||||
*tilde_ptr = '~';
|
|
||||||
|
|
||||||
if ((recieved_value < left_val) ||
|
|
||||||
(recieved_value > right_val)) {
|
|
||||||
pr_err("Illegal response \"%s=%u\", value must"
|
|
||||||
" be between %u and %u.\n", param->name,
|
|
||||||
recieved_value, left_val, right_val);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else if (IS_TYPE_VALUE_LIST(param)) {
|
|
||||||
char *comma_ptr = NULL, *tmp_ptr = NULL;
|
char *comma_ptr = NULL, *tmp_ptr = NULL;
|
||||||
|
|
||||||
comma_ptr = strchr(value, ',');
|
comma_ptr = strchr(value, ',');
|
||||||
|
@ -1361,9 +1177,6 @@ static int iscsi_check_value(struct iscsi_param *param, char *value)
|
||||||
} else if (IS_TYPE_NUMBER(param)) {
|
} else if (IS_TYPE_NUMBER(param)) {
|
||||||
if (iscsi_check_numerical_value(param, value) < 0)
|
if (iscsi_check_numerical_value(param, value) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else if (IS_TYPE_NUMBER_RANGE(param)) {
|
|
||||||
if (iscsi_check_numerical_range_value(param, value) < 0)
|
|
||||||
return -1;
|
|
||||||
} else if (IS_TYPE_STRING(param) || IS_TYPE_VALUE_LIST(param)) {
|
} else if (IS_TYPE_STRING(param) || IS_TYPE_VALUE_LIST(param)) {
|
||||||
if (iscsi_check_string_or_list_value(param, value) < 0)
|
if (iscsi_check_string_or_list_value(param, value) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1483,8 +1296,6 @@ static int iscsi_enforce_integrity_rules(
|
||||||
char *tmpptr;
|
char *tmpptr;
|
||||||
u8 DataSequenceInOrder = 0;
|
u8 DataSequenceInOrder = 0;
|
||||||
u8 ErrorRecoveryLevel = 0, SessionType = 0;
|
u8 ErrorRecoveryLevel = 0, SessionType = 0;
|
||||||
u8 IFMarker = 0, OFMarker = 0;
|
|
||||||
u8 IFMarkInt_Reject = 1, OFMarkInt_Reject = 1;
|
|
||||||
u32 FirstBurstLength = 0, MaxBurstLength = 0;
|
u32 FirstBurstLength = 0, MaxBurstLength = 0;
|
||||||
struct iscsi_param *param = NULL;
|
struct iscsi_param *param = NULL;
|
||||||
|
|
||||||
|
@ -1503,28 +1314,12 @@ static int iscsi_enforce_integrity_rules(
|
||||||
if (!strcmp(param->name, MAXBURSTLENGTH))
|
if (!strcmp(param->name, MAXBURSTLENGTH))
|
||||||
MaxBurstLength = simple_strtoul(param->value,
|
MaxBurstLength = simple_strtoul(param->value,
|
||||||
&tmpptr, 0);
|
&tmpptr, 0);
|
||||||
if (!strcmp(param->name, IFMARKER))
|
|
||||||
if (!strcmp(param->value, YES))
|
|
||||||
IFMarker = 1;
|
|
||||||
if (!strcmp(param->name, OFMARKER))
|
|
||||||
if (!strcmp(param->value, YES))
|
|
||||||
OFMarker = 1;
|
|
||||||
if (!strcmp(param->name, IFMARKINT))
|
|
||||||
if (!strcmp(param->value, REJECT))
|
|
||||||
IFMarkInt_Reject = 1;
|
|
||||||
if (!strcmp(param->name, OFMARKINT))
|
|
||||||
if (!strcmp(param->value, REJECT))
|
|
||||||
OFMarkInt_Reject = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(param, ¶m_list->param_list, p_list) {
|
list_for_each_entry(param, ¶m_list->param_list, p_list) {
|
||||||
if (!(param->phase & phase))
|
if (!(param->phase & phase))
|
||||||
continue;
|
continue;
|
||||||
if (!SessionType && (!IS_PSTATE_ACCEPTOR(param) &&
|
if (!SessionType && !IS_PSTATE_ACCEPTOR(param))
|
||||||
(strcmp(param->name, IFMARKER) &&
|
|
||||||
strcmp(param->name, OFMARKER) &&
|
|
||||||
strcmp(param->name, IFMARKINT) &&
|
|
||||||
strcmp(param->name, OFMARKINT))))
|
|
||||||
continue;
|
continue;
|
||||||
if (!strcmp(param->name, MAXOUTSTANDINGR2T) &&
|
if (!strcmp(param->name, MAXOUTSTANDINGR2T) &&
|
||||||
DataSequenceInOrder && (ErrorRecoveryLevel > 0)) {
|
DataSequenceInOrder && (ErrorRecoveryLevel > 0)) {
|
||||||
|
@ -1556,38 +1351,6 @@ static int iscsi_enforce_integrity_rules(
|
||||||
param->name, param->value);
|
param->name, param->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!strcmp(param->name, IFMARKER) && IFMarkInt_Reject) {
|
|
||||||
if (iscsi_update_param_value(param, NO) < 0)
|
|
||||||
return -1;
|
|
||||||
IFMarker = 0;
|
|
||||||
pr_debug("Reset \"%s\" to \"%s\".\n",
|
|
||||||
param->name, param->value);
|
|
||||||
}
|
|
||||||
if (!strcmp(param->name, OFMARKER) && OFMarkInt_Reject) {
|
|
||||||
if (iscsi_update_param_value(param, NO) < 0)
|
|
||||||
return -1;
|
|
||||||
OFMarker = 0;
|
|
||||||
pr_debug("Reset \"%s\" to \"%s\".\n",
|
|
||||||
param->name, param->value);
|
|
||||||
}
|
|
||||||
if (!strcmp(param->name, IFMARKINT) && !IFMarker) {
|
|
||||||
if (!strcmp(param->value, REJECT))
|
|
||||||
continue;
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
if (iscsi_update_param_value(param, IRRELEVANT) < 0)
|
|
||||||
return -1;
|
|
||||||
pr_debug("Reset \"%s\" to \"%s\".\n",
|
|
||||||
param->name, param->value);
|
|
||||||
}
|
|
||||||
if (!strcmp(param->name, OFMARKINT) && !OFMarker) {
|
|
||||||
if (!strcmp(param->value, REJECT))
|
|
||||||
continue;
|
|
||||||
param->state &= ~PSTATE_NEGOTIATE;
|
|
||||||
if (iscsi_update_param_value(param, IRRELEVANT) < 0)
|
|
||||||
return -1;
|
|
||||||
pr_debug("Reset \"%s\" to \"%s\".\n",
|
|
||||||
param->name, param->value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1824,24 +1587,6 @@ void iscsi_set_connection_parameters(
|
||||||
*/
|
*/
|
||||||
pr_debug("MaxRecvDataSegmentLength: %u\n",
|
pr_debug("MaxRecvDataSegmentLength: %u\n",
|
||||||
ops->MaxRecvDataSegmentLength);
|
ops->MaxRecvDataSegmentLength);
|
||||||
} else if (!strcmp(param->name, OFMARKER)) {
|
|
||||||
ops->OFMarker = !strcmp(param->value, YES);
|
|
||||||
pr_debug("OFMarker: %s\n",
|
|
||||||
param->value);
|
|
||||||
} else if (!strcmp(param->name, IFMARKER)) {
|
|
||||||
ops->IFMarker = !strcmp(param->value, YES);
|
|
||||||
pr_debug("IFMarker: %s\n",
|
|
||||||
param->value);
|
|
||||||
} else if (!strcmp(param->name, OFMARKINT)) {
|
|
||||||
ops->OFMarkInt =
|
|
||||||
simple_strtoul(param->value, &tmpptr, 0);
|
|
||||||
pr_debug("OFMarkInt: %s\n",
|
|
||||||
param->value);
|
|
||||||
} else if (!strcmp(param->name, IFMARKINT)) {
|
|
||||||
ops->IFMarkInt =
|
|
||||||
simple_strtoul(param->value, &tmpptr, 0);
|
|
||||||
pr_debug("IFMarkInt: %s\n",
|
|
||||||
param->value);
|
|
||||||
} else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
|
} else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
|
||||||
ops->InitiatorRecvDataSegmentLength =
|
ops->InitiatorRecvDataSegmentLength =
|
||||||
simple_strtoul(param->value, &tmpptr, 0);
|
simple_strtoul(param->value, &tmpptr, 0);
|
||||||
|
|
|
@ -138,8 +138,8 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
|
||||||
#define INITIAL_SESSIONTYPE NORMAL
|
#define INITIAL_SESSIONTYPE NORMAL
|
||||||
#define INITIAL_IFMARKER NO
|
#define INITIAL_IFMARKER NO
|
||||||
#define INITIAL_OFMARKER NO
|
#define INITIAL_OFMARKER NO
|
||||||
#define INITIAL_IFMARKINT "2048~65535"
|
#define INITIAL_IFMARKINT REJECT
|
||||||
#define INITIAL_OFMARKINT "2048~65535"
|
#define INITIAL_OFMARKINT REJECT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initial values for iSER parameters following RFC-5046 Section 6
|
* Initial values for iSER parameters following RFC-5046 Section 6
|
||||||
|
@ -239,10 +239,9 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
|
||||||
#define TYPERANGE_AUTH 0x0200
|
#define TYPERANGE_AUTH 0x0200
|
||||||
#define TYPERANGE_DIGEST 0x0400
|
#define TYPERANGE_DIGEST 0x0400
|
||||||
#define TYPERANGE_ISCSINAME 0x0800
|
#define TYPERANGE_ISCSINAME 0x0800
|
||||||
#define TYPERANGE_MARKINT 0x1000
|
#define TYPERANGE_SESSIONTYPE 0x1000
|
||||||
#define TYPERANGE_SESSIONTYPE 0x2000
|
#define TYPERANGE_TARGETADDRESS 0x2000
|
||||||
#define TYPERANGE_TARGETADDRESS 0x4000
|
#define TYPERANGE_UTF8 0x4000
|
||||||
#define TYPERANGE_UTF8 0x8000
|
|
||||||
|
|
||||||
#define IS_TYPERANGE_0_TO_2(p) ((p)->type_range & TYPERANGE_0_TO_2)
|
#define IS_TYPERANGE_0_TO_2(p) ((p)->type_range & TYPERANGE_0_TO_2)
|
||||||
#define IS_TYPERANGE_0_TO_3600(p) ((p)->type_range & TYPERANGE_0_TO_3600)
|
#define IS_TYPERANGE_0_TO_3600(p) ((p)->type_range & TYPERANGE_0_TO_3600)
|
||||||
|
|
|
@ -809,54 +809,6 @@ void iscsit_inc_session_usage_count(struct iscsi_session *sess)
|
||||||
spin_unlock_bh(&sess->session_usage_lock);
|
spin_unlock_bh(&sess->session_usage_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup conn->if_marker and conn->of_marker values based upon
|
|
||||||
* the initial marker-less interval. (see iSCSI v19 A.2)
|
|
||||||
*/
|
|
||||||
int iscsit_set_sync_and_steering_values(struct iscsi_conn *conn)
|
|
||||||
{
|
|
||||||
int login_ifmarker_count = 0, login_ofmarker_count = 0, next_marker = 0;
|
|
||||||
/*
|
|
||||||
* IFMarkInt and OFMarkInt are negotiated as 32-bit words.
|
|
||||||
*/
|
|
||||||
u32 IFMarkInt = (conn->conn_ops->IFMarkInt * 4);
|
|
||||||
u32 OFMarkInt = (conn->conn_ops->OFMarkInt * 4);
|
|
||||||
|
|
||||||
if (conn->conn_ops->OFMarker) {
|
|
||||||
/*
|
|
||||||
* Account for the first Login Command received not
|
|
||||||
* via iscsi_recv_msg().
|
|
||||||
*/
|
|
||||||
conn->of_marker += ISCSI_HDR_LEN;
|
|
||||||
if (conn->of_marker <= OFMarkInt) {
|
|
||||||
conn->of_marker = (OFMarkInt - conn->of_marker);
|
|
||||||
} else {
|
|
||||||
login_ofmarker_count = (conn->of_marker / OFMarkInt);
|
|
||||||
next_marker = (OFMarkInt * (login_ofmarker_count + 1)) +
|
|
||||||
(login_ofmarker_count * MARKER_SIZE);
|
|
||||||
conn->of_marker = (next_marker - conn->of_marker);
|
|
||||||
}
|
|
||||||
conn->of_marker_offset = 0;
|
|
||||||
pr_debug("Setting OFMarker value to %u based on Initial"
|
|
||||||
" Markerless Interval.\n", conn->of_marker);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->conn_ops->IFMarker) {
|
|
||||||
if (conn->if_marker <= IFMarkInt) {
|
|
||||||
conn->if_marker = (IFMarkInt - conn->if_marker);
|
|
||||||
} else {
|
|
||||||
login_ifmarker_count = (conn->if_marker / IFMarkInt);
|
|
||||||
next_marker = (IFMarkInt * (login_ifmarker_count + 1)) +
|
|
||||||
(login_ifmarker_count * MARKER_SIZE);
|
|
||||||
conn->if_marker = (next_marker - conn->if_marker);
|
|
||||||
}
|
|
||||||
pr_debug("Setting IFMarker value to %u based on Initial"
|
|
||||||
" Markerless Interval.\n", conn->if_marker);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *sess, u16 cid)
|
struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *sess, u16 cid)
|
||||||
{
|
{
|
||||||
struct iscsi_conn *conn;
|
struct iscsi_conn *conn;
|
||||||
|
|
|
@ -34,7 +34,6 @@ extern void iscsit_free_cmd(struct iscsi_cmd *, bool);
|
||||||
extern int iscsit_check_session_usage_count(struct iscsi_session *);
|
extern int iscsit_check_session_usage_count(struct iscsi_session *);
|
||||||
extern void iscsit_dec_session_usage_count(struct iscsi_session *);
|
extern void iscsit_dec_session_usage_count(struct iscsi_session *);
|
||||||
extern void iscsit_inc_session_usage_count(struct iscsi_session *);
|
extern void iscsit_inc_session_usage_count(struct iscsi_session *);
|
||||||
extern int iscsit_set_sync_and_steering_values(struct iscsi_conn *);
|
|
||||||
extern struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *, u16);
|
extern struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *, u16);
|
||||||
extern struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *, u16);
|
extern struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *, u16);
|
||||||
extern void iscsit_check_conn_usage_count(struct iscsi_conn *);
|
extern void iscsit_check_conn_usage_count(struct iscsi_conn *);
|
||||||
|
|
|
@ -248,10 +248,6 @@ struct iscsi_conn_ops {
|
||||||
u8 DataDigest; /* [0,1] == [None,CRC32C] */
|
u8 DataDigest; /* [0,1] == [None,CRC32C] */
|
||||||
u32 MaxRecvDataSegmentLength; /* [512..2**24-1] */
|
u32 MaxRecvDataSegmentLength; /* [512..2**24-1] */
|
||||||
u32 MaxXmitDataSegmentLength; /* [512..2**24-1] */
|
u32 MaxXmitDataSegmentLength; /* [512..2**24-1] */
|
||||||
u8 OFMarker; /* [0,1] == [No,Yes] */
|
|
||||||
u8 IFMarker; /* [0,1] == [No,Yes] */
|
|
||||||
u32 OFMarkInt; /* [1..65535] */
|
|
||||||
u32 IFMarkInt; /* [1..65535] */
|
|
||||||
/*
|
/*
|
||||||
* iSER specific connection parameters
|
* iSER specific connection parameters
|
||||||
*/
|
*/
|
||||||
|
@ -532,12 +528,6 @@ struct iscsi_conn {
|
||||||
u32 exp_statsn;
|
u32 exp_statsn;
|
||||||
/* Per connection status sequence number */
|
/* Per connection status sequence number */
|
||||||
u32 stat_sn;
|
u32 stat_sn;
|
||||||
/* IFMarkInt's Current Value */
|
|
||||||
u32 if_marker;
|
|
||||||
/* OFMarkInt's Current Value */
|
|
||||||
u32 of_marker;
|
|
||||||
/* Used for calculating OFMarker offset to next PDU */
|
|
||||||
u32 of_marker_offset;
|
|
||||||
#define IPV6_ADDRESS_SPACE 48
|
#define IPV6_ADDRESS_SPACE 48
|
||||||
unsigned char login_ip[IPV6_ADDRESS_SPACE];
|
unsigned char login_ip[IPV6_ADDRESS_SPACE];
|
||||||
unsigned char local_ip[IPV6_ADDRESS_SPACE];
|
unsigned char local_ip[IPV6_ADDRESS_SPACE];
|
||||||
|
|
Загрузка…
Ссылка в новой задаче