2011-07-23 10:43:04 +04:00
/*******************************************************************************
* This file contains main functions related to iSCSI Parameter negotiation .
*
* \ u00a9 Copyright 2007 - 2011 RisingTide Systems LLC .
*
* Licensed to the Linux Foundation under the General Public License ( GPL ) version 2.
*
* Author : Nicholas A . Bellinger < nab @ linux - iscsi . org >
*
* 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/slab.h>
# include "iscsi_target_core.h"
# include "iscsi_target_util.h"
# include "iscsi_target_parameters.h"
int iscsi_login_rx_data (
struct iscsi_conn * conn ,
char * buf ,
int length )
{
int rx_got ;
struct kvec iov ;
memset ( & iov , 0 , sizeof ( struct kvec ) ) ;
iov . iov_len = length ;
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 ) ;
if ( rx_got ! = length ) {
pr_err ( " rx_data returned %d, expecting %d. \n " ,
rx_got , length ) ;
return - 1 ;
}
return 0 ;
}
int iscsi_login_tx_data (
struct iscsi_conn * conn ,
char * pdu_buf ,
char * text_buf ,
int text_length )
{
int length , tx_sent ;
struct kvec iov [ 2 ] ;
length = ( ISCSI_HDR_LEN + text_length ) ;
memset ( & iov [ 0 ] , 0 , 2 * sizeof ( struct kvec ) ) ;
iov [ 0 ] . iov_len = ISCSI_HDR_LEN ;
iov [ 0 ] . iov_base = pdu_buf ;
iov [ 1 ] . iov_len = text_length ;
iov [ 1 ] . iov_base = text_buf ;
/*
* 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 ] , 2 , length ) ;
if ( tx_sent ! = length ) {
pr_err ( " tx_data returned %d, expecting %d. \n " ,
tx_sent , length ) ;
return - 1 ;
}
return 0 ;
}
void iscsi_dump_conn_ops ( struct iscsi_conn_ops * conn_ops )
{
pr_debug ( " HeaderDigest: %s \n " , ( conn_ops - > HeaderDigest ) ?
" CRC32C " : " None " ) ;
pr_debug ( " DataDigest: %s \n " , ( conn_ops - > DataDigest ) ?
" CRC32C " : " None " ) ;
pr_debug ( " MaxRecvDataSegmentLength: %u \n " ,
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 )
{
pr_debug ( " InitiatorName: %s \n " , sess_ops - > InitiatorName ) ;
pr_debug ( " InitiatorAlias: %s \n " , sess_ops - > InitiatorAlias ) ;
pr_debug ( " TargetName: %s \n " , sess_ops - > TargetName ) ;
pr_debug ( " TargetAlias: %s \n " , sess_ops - > TargetAlias ) ;
pr_debug ( " TargetPortalGroupTag: %hu \n " ,
sess_ops - > TargetPortalGroupTag ) ;
pr_debug ( " MaxConnections: %hu \n " , sess_ops - > MaxConnections ) ;
pr_debug ( " InitialR2T: %s \n " ,
( sess_ops - > InitialR2T ) ? " Yes " : " No " ) ;
pr_debug ( " ImmediateData: %s \n " , ( sess_ops - > ImmediateData ) ?
" Yes " : " No " ) ;
pr_debug ( " MaxBurstLength: %u \n " , sess_ops - > MaxBurstLength ) ;
pr_debug ( " FirstBurstLength: %u \n " , sess_ops - > FirstBurstLength ) ;
pr_debug ( " DefaultTime2Wait: %hu \n " , sess_ops - > DefaultTime2Wait ) ;
pr_debug ( " DefaultTime2Retain: %hu \n " ,
sess_ops - > DefaultTime2Retain ) ;
pr_debug ( " MaxOutstandingR2T: %hu \n " ,
sess_ops - > MaxOutstandingR2T ) ;
pr_debug ( " DataPDUInOrder: %s \n " ,
( sess_ops - > DataPDUInOrder ) ? " Yes " : " No " ) ;
pr_debug ( " DataSequenceInOrder: %s \n " ,
( sess_ops - > DataSequenceInOrder ) ? " Yes " : " No " ) ;
pr_debug ( " ErrorRecoveryLevel: %hu \n " ,
sess_ops - > ErrorRecoveryLevel ) ;
pr_debug ( " SessionType: %s \n " , ( sess_ops - > SessionType ) ?
" Discovery " : " Normal " ) ;
}
void iscsi_print_params ( struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
list_for_each_entry ( param , & param_list - > param_list , p_list )
pr_debug ( " %s: %s \n " , param - > name , param - > value ) ;
}
static struct iscsi_param * iscsi_set_default_param ( struct iscsi_param_list * param_list ,
char * name , char * value , u8 phase , u8 scope , u8 sender ,
u16 type_range , u8 use )
{
struct iscsi_param * param = NULL ;
param = kzalloc ( sizeof ( struct iscsi_param ) , GFP_KERNEL ) ;
if ( ! param ) {
pr_err ( " Unable to allocate memory for parameter. \n " ) ;
goto out ;
}
INIT_LIST_HEAD ( & param - > p_list ) ;
param - > name = kzalloc ( strlen ( name ) + 1 , GFP_KERNEL ) ;
if ( ! param - > name ) {
pr_err ( " Unable to allocate memory for parameter name. \n " ) ;
goto out ;
}
param - > value = kzalloc ( strlen ( value ) + 1 , GFP_KERNEL ) ;
if ( ! param - > value ) {
pr_err ( " Unable to allocate memory for parameter value. \n " ) ;
goto out ;
}
memcpy ( param - > name , name , strlen ( name ) ) ;
param - > name [ strlen ( name ) ] = ' \0 ' ;
memcpy ( param - > value , value , strlen ( value ) ) ;
param - > value [ strlen ( value ) ] = ' \0 ' ;
param - > phase = phase ;
param - > scope = scope ;
param - > sender = sender ;
param - > use = use ;
param - > type_range = type_range ;
switch ( param - > type_range ) {
case TYPERANGE_BOOL_AND :
param - > type = TYPE_BOOL_AND ;
break ;
case TYPERANGE_BOOL_OR :
param - > type = TYPE_BOOL_OR ;
break ;
case TYPERANGE_0_TO_2 :
case TYPERANGE_0_TO_3600 :
case TYPERANGE_0_TO_32767 :
case TYPERANGE_0_TO_65535 :
case TYPERANGE_1_TO_65535 :
case TYPERANGE_2_TO_3600 :
case TYPERANGE_512_TO_16777215 :
param - > type = TYPE_NUMBER ;
break ;
case TYPERANGE_AUTH :
case TYPERANGE_DIGEST :
param - > type = TYPE_VALUE_LIST | TYPE_STRING ;
break ;
case TYPERANGE_MARKINT :
param - > type = TYPE_NUMBER_RANGE ;
param - > type_range | = TYPERANGE_1_TO_65535 ;
break ;
case TYPERANGE_ISCSINAME :
case TYPERANGE_SESSIONTYPE :
case TYPERANGE_TARGETADDRESS :
case TYPERANGE_UTF8 :
param - > type = TYPE_STRING ;
break ;
default :
pr_err ( " Unknown type_range 0x%02x \n " ,
param - > type_range ) ;
goto out ;
}
list_add_tail ( & param - > p_list , & param_list - > param_list ) ;
return param ;
out :
if ( param ) {
kfree ( param - > value ) ;
kfree ( param - > name ) ;
kfree ( param ) ;
}
return NULL ;
}
/* #warning Add extension keys */
int iscsi_create_default_params ( struct iscsi_param_list * * param_list_ptr )
{
struct iscsi_param * param = NULL ;
struct iscsi_param_list * pl ;
pl = kzalloc ( sizeof ( struct iscsi_param_list ) , GFP_KERNEL ) ;
if ( ! pl ) {
pr_err ( " Unable to allocate memory for "
" struct iscsi_param_list. \n " ) ;
return - 1 ;
}
INIT_LIST_HEAD ( & pl - > param_list ) ;
INIT_LIST_HEAD ( & pl - > extra_response_list ) ;
/*
* The format for setting the initial parameter definitions are :
*
* Parameter name :
* Initial value :
* Allowable phase :
* Scope :
* Allowable senders :
* Typerange :
* Use :
*/
param = iscsi_set_default_param ( pl , AUTHMETHOD , INITIAL_AUTHMETHOD ,
PHASE_SECURITY , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_AUTH , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , HEADERDIGEST , INITIAL_HEADERDIGEST ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_DIGEST , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , DATADIGEST , INITIAL_DATADIGEST ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_DIGEST , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , MAXCONNECTIONS ,
INITIAL_MAXCONNECTIONS , PHASE_OPERATIONAL ,
SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_1_TO_65535 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , SENDTARGETS , INITIAL_SENDTARGETS ,
PHASE_FFP0 , SCOPE_SESSION_WIDE , SENDER_INITIATOR ,
TYPERANGE_UTF8 , 0 ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , TARGETNAME , INITIAL_TARGETNAME ,
PHASE_DECLARATIVE , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_ISCSINAME , USE_ALL ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , INITIATORNAME ,
INITIAL_INITIATORNAME , PHASE_DECLARATIVE ,
SCOPE_SESSION_WIDE , SENDER_INITIATOR ,
TYPERANGE_ISCSINAME , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , TARGETALIAS , INITIAL_TARGETALIAS ,
PHASE_DECLARATIVE , SCOPE_SESSION_WIDE , SENDER_TARGET ,
TYPERANGE_UTF8 , USE_ALL ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , INITIATORALIAS ,
INITIAL_INITIATORALIAS , PHASE_DECLARATIVE ,
SCOPE_SESSION_WIDE , SENDER_INITIATOR , TYPERANGE_UTF8 ,
USE_ALL ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , TARGETADDRESS ,
INITIAL_TARGETADDRESS , PHASE_DECLARATIVE ,
SCOPE_SESSION_WIDE , SENDER_TARGET ,
TYPERANGE_TARGETADDRESS , USE_ALL ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , TARGETPORTALGROUPTAG ,
INITIAL_TARGETPORTALGROUPTAG ,
PHASE_DECLARATIVE , SCOPE_SESSION_WIDE , SENDER_TARGET ,
TYPERANGE_0_TO_65535 , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , INITIALR2T , INITIAL_INITIALR2T ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_BOOL_OR , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , IMMEDIATEDATA ,
INITIAL_IMMEDIATEDATA , PHASE_OPERATIONAL ,
SCOPE_SESSION_WIDE , SENDER_BOTH , TYPERANGE_BOOL_AND ,
USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , MAXRECVDATASEGMENTLENGTH ,
INITIAL_MAXRECVDATASEGMENTLENGTH ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_512_TO_16777215 , USE_ALL ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , MAXBURSTLENGTH ,
INITIAL_MAXBURSTLENGTH , PHASE_OPERATIONAL ,
SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_512_TO_16777215 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , FIRSTBURSTLENGTH ,
INITIAL_FIRSTBURSTLENGTH ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_512_TO_16777215 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , DEFAULTTIME2WAIT ,
INITIAL_DEFAULTTIME2WAIT ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_0_TO_3600 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , DEFAULTTIME2RETAIN ,
INITIAL_DEFAULTTIME2RETAIN ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_0_TO_3600 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , MAXOUTSTANDINGR2T ,
INITIAL_MAXOUTSTANDINGR2T ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_1_TO_65535 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , DATAPDUINORDER ,
INITIAL_DATAPDUINORDER , PHASE_OPERATIONAL ,
SCOPE_SESSION_WIDE , SENDER_BOTH , TYPERANGE_BOOL_OR ,
USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , DATASEQUENCEINORDER ,
INITIAL_DATASEQUENCEINORDER ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_BOOL_OR , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , ERRORRECOVERYLEVEL ,
INITIAL_ERRORRECOVERYLEVEL ,
PHASE_OPERATIONAL , SCOPE_SESSION_WIDE , SENDER_BOTH ,
TYPERANGE_0_TO_2 , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , SESSIONTYPE , INITIAL_SESSIONTYPE ,
PHASE_DECLARATIVE , SCOPE_SESSION_WIDE , SENDER_INITIATOR ,
TYPERANGE_SESSIONTYPE , USE_LEADING_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , IFMARKER , INITIAL_IFMARKER ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_BOOL_AND , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , OFMARKER , INITIAL_OFMARKER ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_BOOL_AND , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , IFMARKINT , INITIAL_IFMARKINT ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_MARKINT , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
param = iscsi_set_default_param ( pl , OFMARKINT , INITIAL_OFMARKINT ,
PHASE_OPERATIONAL , SCOPE_CONNECTION_ONLY , SENDER_BOTH ,
TYPERANGE_MARKINT , USE_INITIAL_ONLY ) ;
if ( ! param )
goto out ;
* param_list_ptr = pl ;
return 0 ;
out :
iscsi_release_param_list ( pl ) ;
return - 1 ;
}
int iscsi_set_keys_to_negotiate (
int sessiontype ,
struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
param - > state = 0 ;
if ( ! strcmp ( param - > name , AUTHMETHOD ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , HEADERDIGEST ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , DATADIGEST ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , MAXCONNECTIONS ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , TARGETNAME ) ) {
continue ;
} else if ( ! strcmp ( param - > name , INITIATORNAME ) ) {
continue ;
} else if ( ! strcmp ( param - > name , TARGETALIAS ) ) {
if ( param - > value )
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , INITIATORALIAS ) ) {
continue ;
} else if ( ! strcmp ( param - > name , TARGETPORTALGROUPTAG ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , INITIALR2T ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , IMMEDIATEDATA ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , MAXRECVDATASEGMENTLENGTH ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , MAXBURSTLENGTH ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , FIRSTBURSTLENGTH ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , DEFAULTTIME2WAIT ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , DEFAULTTIME2RETAIN ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , MAXOUTSTANDINGR2T ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , DATAPDUINORDER ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , DATASEQUENCEINORDER ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , ERRORRECOVERYLEVEL ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , SESSIONTYPE ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , IFMARKER ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , OFMARKER ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , IFMARKINT ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
} else if ( ! strcmp ( param - > name , OFMARKINT ) ) {
SET_PSTATE_NEGOTIATE ( param ) ;
}
}
return 0 ;
}
int iscsi_set_keys_irrelevant_for_discovery (
struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! strcmp ( param - > name , MAXCONNECTIONS ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , INITIALR2T ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , IMMEDIATEDATA ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , MAXBURSTLENGTH ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , FIRSTBURSTLENGTH ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , MAXOUTSTANDINGR2T ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , DATAPDUINORDER ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , DATASEQUENCEINORDER ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , ERRORRECOVERYLEVEL ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , DEFAULTTIME2WAIT ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , DEFAULTTIME2RETAIN ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , IFMARKER ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , OFMARKER ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , IFMARKINT ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
else if ( ! strcmp ( param - > name , OFMARKINT ) )
param - > state & = ~ PSTATE_NEGOTIATE ;
}
return 0 ;
}
int iscsi_copy_param_list (
struct iscsi_param_list * * dst_param_list ,
struct iscsi_param_list * src_param_list ,
int leading )
{
2011-08-02 12:26:36 +04:00
struct iscsi_param * param = NULL ;
struct iscsi_param * new_param = NULL ;
2011-07-23 10:43:04 +04:00
struct iscsi_param_list * param_list = NULL ;
param_list = kzalloc ( sizeof ( struct iscsi_param_list ) , GFP_KERNEL ) ;
if ( ! param_list ) {
2011-08-02 12:26:36 +04:00
pr_err ( " Unable to allocate memory for struct iscsi_param_list. \n " ) ;
2011-07-23 10:43:04 +04:00
goto err_out ;
}
INIT_LIST_HEAD ( & param_list - > param_list ) ;
INIT_LIST_HEAD ( & param_list - > extra_response_list ) ;
list_for_each_entry ( param , & src_param_list - > param_list , p_list ) {
if ( ! leading & & ( param - > scope & SCOPE_SESSION_WIDE ) ) {
if ( ( strcmp ( param - > name , " TargetName " ) ! = 0 ) & &
( strcmp ( param - > name , " InitiatorName " ) ! = 0 ) & &
( strcmp ( param - > name , " TargetPortalGroupTag " ) ! = 0 ) )
continue ;
}
new_param = kzalloc ( sizeof ( struct iscsi_param ) , GFP_KERNEL ) ;
if ( ! new_param ) {
2011-08-02 12:26:36 +04:00
pr_err ( " Unable to allocate memory for struct iscsi_param. \n " ) ;
goto err_out ;
}
new_param - > name = kstrdup ( param - > name , GFP_KERNEL ) ;
new_param - > value = kstrdup ( param - > value , GFP_KERNEL ) ;
if ( ! new_param - > value | | ! new_param - > name ) {
kfree ( new_param - > value ) ;
kfree ( new_param - > name ) ;
kfree ( new_param ) ;
pr_err ( " Unable to allocate memory for parameter name/value. \n " ) ;
2011-07-23 10:43:04 +04:00
goto err_out ;
}
new_param - > set_param = param - > set_param ;
new_param - > phase = param - > phase ;
new_param - > scope = param - > scope ;
new_param - > sender = param - > sender ;
new_param - > type = param - > type ;
new_param - > use = param - > use ;
new_param - > type_range = param - > type_range ;
list_add_tail ( & new_param - > p_list , & param_list - > param_list ) ;
}
2011-08-02 12:26:36 +04:00
if ( ! list_empty ( & param_list - > param_list ) ) {
2011-07-23 10:43:04 +04:00
* dst_param_list = param_list ;
2011-08-02 12:26:36 +04:00
} else {
2011-07-23 10:43:04 +04:00
pr_err ( " No parameters allocated. \n " ) ;
goto err_out ;
}
return 0 ;
err_out :
iscsi_release_param_list ( param_list ) ;
return - 1 ;
}
static void iscsi_release_extra_responses ( struct iscsi_param_list * param_list )
{
struct iscsi_extra_response * er , * er_tmp ;
list_for_each_entry_safe ( er , er_tmp , & param_list - > extra_response_list ,
er_list ) {
list_del ( & er - > er_list ) ;
kfree ( er ) ;
}
}
void iscsi_release_param_list ( struct iscsi_param_list * param_list )
{
struct iscsi_param * param , * param_tmp ;
list_for_each_entry_safe ( param , param_tmp , & param_list - > param_list ,
p_list ) {
list_del ( & param - > p_list ) ;
kfree ( param - > name ) ;
param - > name = NULL ;
kfree ( param - > value ) ;
param - > value = NULL ;
kfree ( param ) ;
param = NULL ;
}
iscsi_release_extra_responses ( param_list ) ;
kfree ( param_list ) ;
}
struct iscsi_param * iscsi_find_param_from_key (
char * key ,
struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
if ( ! key | | ! param_list ) {
pr_err ( " Key or parameter list pointer is NULL. \n " ) ;
return NULL ;
}
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! strcmp ( key , param - > name ) )
return param ;
}
pr_err ( " Unable to locate key \" %s \" . \n " , key ) ;
return NULL ;
}
int iscsi_extract_key_value ( char * textbuf , char * * key , char * * value )
{
* value = strchr ( textbuf , ' = ' ) ;
if ( ! * value ) {
pr_err ( " Unable to locate \" = \" seperator for key, "
" ignoring request. \n " ) ;
return - 1 ;
}
* key = textbuf ;
* * value = ' \0 ' ;
* value = * value + 1 ;
return 0 ;
}
int iscsi_update_param_value ( struct iscsi_param * param , char * value )
{
kfree ( param - > value ) ;
param - > value = kzalloc ( strlen ( value ) + 1 , GFP_KERNEL ) ;
if ( ! param - > value ) {
pr_err ( " Unable to allocate memory for value. \n " ) ;
2012-07-13 04:34:56 +04:00
return - ENOMEM ;
2011-07-23 10:43:04 +04:00
}
memcpy ( param - > value , value , strlen ( value ) ) ;
param - > value [ strlen ( value ) ] = ' \0 ' ;
pr_debug ( " iSCSI Parameter updated to %s=%s \n " ,
param - > name , param - > value ) ;
return 0 ;
}
static int iscsi_add_notunderstood_response (
char * key ,
char * value ,
struct iscsi_param_list * param_list )
{
struct iscsi_extra_response * extra_response ;
if ( strlen ( value ) > VALUE_MAXLEN ) {
pr_err ( " Value for notunderstood key \" %s \" exceeds %d, "
" protocol error. \n " , key , VALUE_MAXLEN ) ;
return - 1 ;
}
extra_response = kzalloc ( sizeof ( struct iscsi_extra_response ) , GFP_KERNEL ) ;
if ( ! extra_response ) {
pr_err ( " Unable to allocate memory for "
" struct iscsi_extra_response. \n " ) ;
return - 1 ;
}
INIT_LIST_HEAD ( & extra_response - > er_list ) ;
strncpy ( extra_response - > key , key , strlen ( key ) + 1 ) ;
strncpy ( extra_response - > value , NOTUNDERSTOOD ,
strlen ( NOTUNDERSTOOD ) + 1 ) ;
list_add_tail ( & extra_response - > er_list ,
& param_list - > extra_response_list ) ;
return 0 ;
}
static int iscsi_check_for_auth_key ( char * key )
{
/*
* RFC 1994
*/
if ( ! strcmp ( key , " CHAP_A " ) | | ! strcmp ( key , " CHAP_I " ) | |
! strcmp ( key , " CHAP_C " ) | | ! strcmp ( key , " CHAP_N " ) | |
! strcmp ( key , " CHAP_R " ) )
return 1 ;
/*
* RFC 2945
*/
if ( ! strcmp ( key , " SRP_U " ) | | ! strcmp ( key , " SRP_N " ) | |
! strcmp ( key , " SRP_g " ) | | ! strcmp ( key , " SRP_s " ) | |
! strcmp ( key , " SRP_A " ) | | ! strcmp ( key , " SRP_B " ) | |
! strcmp ( key , " SRP_M " ) | | ! strcmp ( key , " SRP_HM " ) )
return 1 ;
return 0 ;
}
static void iscsi_check_proposer_for_optional_reply ( struct iscsi_param * param )
{
if ( IS_TYPE_BOOL_AND ( param ) ) {
if ( ! strcmp ( param - > value , NO ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
} else if ( IS_TYPE_BOOL_OR ( param ) ) {
if ( ! strcmp ( param - > value , YES ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
/*
* Required for gPXE iSCSI boot client
*/
if ( ! strcmp ( param - > name , IMMEDIATEDATA ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
} else if ( IS_TYPE_NUMBER ( param ) ) {
if ( ! strcmp ( param - > name , MAXRECVDATASEGMENTLENGTH ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
/*
* The GlobalSAN iSCSI Initiator for MacOSX does
* not respond to MaxBurstLength , FirstBurstLength ,
* DefaultTime2Wait or DefaultTime2Retain parameter keys .
* So , we set them to ' reply optional ' here , and assume the
* the defaults from iscsi_parameters . h if the initiator
* is not RFC compliant and the keys are not negotiated .
*/
if ( ! strcmp ( param - > name , MAXBURSTLENGTH ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
if ( ! strcmp ( param - > name , FIRSTBURSTLENGTH ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
if ( ! strcmp ( param - > name , DEFAULTTIME2WAIT ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
if ( ! strcmp ( param - > name , DEFAULTTIME2RETAIN ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
/*
* Required for gPXE iSCSI boot client
*/
if ( ! strcmp ( param - > name , MAXCONNECTIONS ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
} else if ( IS_PHASE_DECLARATIVE ( param ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
}
static int iscsi_check_boolean_value ( struct iscsi_param * param , char * value )
{
if ( strcmp ( value , YES ) & & strcmp ( value , NO ) ) {
pr_err ( " Illegal value for \" %s \" , must be either "
" \" %s \" or \" %s \" . \n " , param - > name , YES , NO ) ;
return - 1 ;
}
return 0 ;
}
static int iscsi_check_numerical_value ( struct iscsi_param * param , char * value_ptr )
{
char * tmpptr ;
int value = 0 ;
value = simple_strtoul ( value_ptr , & tmpptr , 0 ) ;
if ( IS_TYPERANGE_0_TO_2 ( param ) ) {
if ( ( value < 0 ) | | ( value > 2 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 0 and 2. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_0_TO_3600 ( param ) ) {
if ( ( value < 0 ) | | ( value > 3600 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 0 and 3600. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_0_TO_32767 ( param ) ) {
if ( ( value < 0 ) | | ( value > 32767 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 0 and 32767. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_0_TO_65535 ( param ) ) {
if ( ( value < 0 ) | | ( value > 65535 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 0 and 65535. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_1_TO_65535 ( param ) ) {
if ( ( value < 1 ) | | ( value > 65535 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 1 and 65535. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_2_TO_3600 ( param ) ) {
if ( ( value < 2 ) | | ( value > 3600 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 2 and 3600. \n " , param - > name ) ;
return - 1 ;
}
return 0 ;
}
if ( IS_TYPERANGE_512_TO_16777215 ( param ) ) {
if ( ( value < 512 ) | | ( value > 16777215 ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" between 512 and 16777215. \n " , param - > name ) ;
return - 1 ;
}
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 ;
2012-03-15 23:08:03 +04:00
char * tilde_ptr = NULL ;
u32 left_val , right_val , local_left_val ;
2011-07-23 10:43:04 +04:00
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 ;
2012-03-15 23:08:03 +04:00
left_val = simple_strtoul ( left_val_ptr , NULL , 0 ) ;
right_val = simple_strtoul ( right_val_ptr , NULL , 0 ) ;
2011-07-23 10:43:04 +04:00
* 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 ;
2012-03-15 23:08:03 +04:00
local_left_val = simple_strtoul ( left_val_ptr , NULL , 0 ) ;
2011-07-23 10:43:04 +04:00
* 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 )
{
if ( IS_PSTATE_PROPOSER ( param ) )
return 0 ;
if ( IS_TYPERANGE_AUTH_PARAM ( param ) ) {
if ( strcmp ( value , KRB5 ) & & strcmp ( value , SPKM1 ) & &
strcmp ( value , SPKM2 ) & & strcmp ( value , SRP ) & &
strcmp ( value , CHAP ) & & strcmp ( value , NONE ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" \" %s \" , \" %s \" , \" %s \" , \" %s \" , \" %s \" "
" or \" %s \" . \n " , param - > name , KRB5 ,
SPKM1 , SPKM2 , SRP , CHAP , NONE ) ;
return - 1 ;
}
}
if ( IS_TYPERANGE_DIGEST_PARAM ( param ) ) {
if ( strcmp ( value , CRC32C ) & & strcmp ( value , NONE ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" \" %s \" or \" %s \" . \n " , param - > name ,
CRC32C , NONE ) ;
return - 1 ;
}
}
if ( IS_TYPERANGE_SESSIONTYPE ( param ) ) {
if ( strcmp ( value , DISCOVERY ) & & strcmp ( value , NORMAL ) ) {
pr_err ( " Illegal value for \" %s \" , must be "
" \" %s \" or \" %s \" . \n " , param - > name ,
DISCOVERY , NORMAL ) ;
return - 1 ;
}
}
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 (
struct iscsi_param * param ,
char * value )
{
char * tmp1 = NULL , * tmp2 = NULL ;
char * acceptor_values = NULL , * proposer_values = NULL ;
acceptor_values = param - > value ;
proposer_values = value ;
do {
if ( ! proposer_values )
return NULL ;
tmp1 = strchr ( proposer_values , ' , ' ) ;
if ( tmp1 )
* tmp1 = ' \0 ' ;
acceptor_values = param - > value ;
do {
if ( ! acceptor_values ) {
if ( tmp1 )
* tmp1 = ' , ' ;
return NULL ;
}
tmp2 = strchr ( acceptor_values , ' , ' ) ;
if ( tmp2 )
* tmp2 = ' \0 ' ;
if ( ! strcmp ( acceptor_values , proposer_values ) ) {
if ( tmp2 )
* tmp2 = ' , ' ;
goto out ;
}
if ( tmp2 )
* tmp2 + + = ' , ' ;
acceptor_values = tmp2 ;
} while ( acceptor_values ) ;
if ( tmp1 )
* tmp1 + + = ' , ' ;
proposer_values = tmp1 ;
} while ( proposer_values ) ;
out :
return proposer_values ;
}
static int iscsi_check_acceptor_state ( struct iscsi_param * param , char * value )
{
u8 acceptor_boolean_value = 0 , proposer_boolean_value = 0 ;
char * negoitated_value = NULL ;
if ( IS_PSTATE_ACCEPTOR ( param ) ) {
pr_err ( " Received key \" %s \" twice, protocol error. \n " ,
param - > name ) ;
return - 1 ;
}
if ( IS_PSTATE_REJECT ( param ) )
return 0 ;
if ( IS_TYPE_BOOL_AND ( param ) ) {
if ( ! strcmp ( value , YES ) )
proposer_boolean_value = 1 ;
if ( ! strcmp ( param - > value , YES ) )
acceptor_boolean_value = 1 ;
if ( acceptor_boolean_value & & proposer_boolean_value )
do { } while ( 0 ) ;
else {
if ( iscsi_update_param_value ( param , NO ) < 0 )
return - 1 ;
if ( ! proposer_boolean_value )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
}
} else if ( IS_TYPE_BOOL_OR ( param ) ) {
if ( ! strcmp ( value , YES ) )
proposer_boolean_value = 1 ;
if ( ! strcmp ( param - > value , YES ) )
acceptor_boolean_value = 1 ;
if ( acceptor_boolean_value | | proposer_boolean_value ) {
if ( iscsi_update_param_value ( param , YES ) < 0 )
return - 1 ;
if ( proposer_boolean_value )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
}
} else if ( IS_TYPE_NUMBER ( param ) ) {
char * tmpptr , buf [ 10 ] ;
u32 acceptor_value = simple_strtoul ( param - > value , & tmpptr , 0 ) ;
u32 proposer_value = simple_strtoul ( value , & tmpptr , 0 ) ;
memset ( buf , 0 , 10 ) ;
if ( ! strcmp ( param - > name , MAXCONNECTIONS ) | |
! strcmp ( param - > name , MAXBURSTLENGTH ) | |
! strcmp ( param - > name , FIRSTBURSTLENGTH ) | |
! strcmp ( param - > name , MAXOUTSTANDINGR2T ) | |
! strcmp ( param - > name , DEFAULTTIME2RETAIN ) | |
! strcmp ( param - > name , ERRORRECOVERYLEVEL ) ) {
if ( proposer_value > acceptor_value ) {
sprintf ( buf , " %u " , acceptor_value ) ;
if ( iscsi_update_param_value ( param ,
& buf [ 0 ] ) < 0 )
return - 1 ;
} else {
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
}
} else if ( ! strcmp ( param - > name , DEFAULTTIME2WAIT ) ) {
if ( acceptor_value > proposer_value ) {
sprintf ( buf , " %u " , acceptor_value ) ;
if ( iscsi_update_param_value ( param ,
& buf [ 0 ] ) < 0 )
return - 1 ;
} else {
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
}
} else {
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
}
if ( ! strcmp ( param - > name , MAXRECVDATASEGMENTLENGTH ) )
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
} 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 ) ) {
negoitated_value = iscsi_check_valuelist_for_support (
param , value ) ;
if ( ! negoitated_value ) {
pr_err ( " Proposer's value list \" %s \" contains "
" no valid values from Acceptor's value list "
" \" %s \" . \n " , value , param - > value ) ;
return - 1 ;
}
if ( iscsi_update_param_value ( param , negoitated_value ) < 0 )
return - 1 ;
} else if ( IS_PHASE_DECLARATIVE ( param ) ) {
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
SET_PSTATE_REPLY_OPTIONAL ( param ) ;
}
return 0 ;
}
static int iscsi_check_proposer_state ( struct iscsi_param * param , char * value )
{
if ( IS_PSTATE_RESPONSE_GOT ( param ) ) {
pr_err ( " Received key \" %s \" twice, protocol error. \n " ,
param - > name ) ;
return - 1 ;
}
if ( IS_TYPE_NUMBER_RANGE ( param ) ) {
u32 left_val = 0 , right_val = 0 , recieved_value = 0 ;
char * left_val_ptr = NULL , * right_val_ptr = NULL ;
2012-03-15 23:08:03 +04:00
char * tilde_ptr = NULL ;
2011-07-23 10:43:04 +04:00
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 ;
2012-03-15 23:08:03 +04:00
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 ) ;
2011-07-23 10:43:04 +04:00
* 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 ;
comma_ptr = strchr ( value , ' , ' ) ;
if ( comma_ptr ) {
pr_err ( " Illegal \" , \" in response for \" %s \" . \n " ,
param - > name ) ;
return - 1 ;
}
tmp_ptr = iscsi_check_valuelist_for_support ( param , value ) ;
if ( ! tmp_ptr )
return - 1 ;
}
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
return 0 ;
}
static int iscsi_check_value ( struct iscsi_param * param , char * value )
{
char * comma_ptr = NULL ;
if ( ! strcmp ( value , REJECT ) ) {
if ( ! strcmp ( param - > name , IFMARKINT ) | |
! strcmp ( param - > name , OFMARKINT ) ) {
/*
* Reject is not fatal for [ I , O ] FMarkInt , and causes
* [ I , O ] FMarker to be reset to No . ( See iSCSI v20 A .3 .2 )
*/
SET_PSTATE_REJECT ( param ) ;
return 0 ;
}
pr_err ( " Received %s=%s \n " , param - > name , value ) ;
return - 1 ;
}
if ( ! strcmp ( value , IRRELEVANT ) ) {
pr_debug ( " Received %s=%s \n " , param - > name , value ) ;
SET_PSTATE_IRRELEVANT ( param ) ;
return 0 ;
}
if ( ! strcmp ( value , NOTUNDERSTOOD ) ) {
if ( ! IS_PSTATE_PROPOSER ( param ) ) {
pr_err ( " Received illegal offer %s=%s \n " ,
param - > name , value ) ;
return - 1 ;
}
/* #warning FIXME: Add check for X-ExtensionKey here */
pr_err ( " Standard iSCSI key \" %s \" cannot be answered "
" with \" %s \" , protocol error. \n " , param - > name , value ) ;
return - 1 ;
}
do {
comma_ptr = NULL ;
comma_ptr = strchr ( value , ' , ' ) ;
if ( comma_ptr & & ! IS_TYPE_VALUE_LIST ( param ) ) {
pr_err ( " Detected value seperator \" , \" , but "
" key \" %s \" does not allow a value list, "
" protocol error. \n " , param - > name ) ;
return - 1 ;
}
if ( comma_ptr )
* comma_ptr = ' \0 ' ;
if ( strlen ( value ) > VALUE_MAXLEN ) {
pr_err ( " Value for key \" %s \" exceeds %d, "
" protocol error. \n " , param - > name ,
VALUE_MAXLEN ) ;
return - 1 ;
}
if ( IS_TYPE_BOOL_AND ( param ) | | IS_TYPE_BOOL_OR ( param ) ) {
if ( iscsi_check_boolean_value ( param , value ) < 0 )
return - 1 ;
} else if ( IS_TYPE_NUMBER ( param ) ) {
if ( iscsi_check_numerical_value ( param , value ) < 0 )
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 ) ) {
if ( iscsi_check_string_or_list_value ( param , value ) < 0 )
return - 1 ;
} else {
pr_err ( " Huh? 0x%02x \n " , param - > type ) ;
return - 1 ;
}
if ( comma_ptr )
* comma_ptr + + = ' , ' ;
value = comma_ptr ;
} while ( value ) ;
return 0 ;
}
static struct iscsi_param * __iscsi_check_key (
char * key ,
int sender ,
struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
if ( strlen ( key ) > KEY_MAXLEN ) {
pr_err ( " Length of key name \" %s \" exceeds %d. \n " ,
key , KEY_MAXLEN ) ;
return NULL ;
}
param = iscsi_find_param_from_key ( key , param_list ) ;
if ( ! param )
return NULL ;
if ( ( sender & SENDER_INITIATOR ) & & ! IS_SENDER_INITIATOR ( param ) ) {
pr_err ( " Key \" %s \" may not be sent to %s, "
" protocol error. \n " , param - > name ,
( sender & SENDER_RECEIVER ) ? " target " : " initiator " ) ;
return NULL ;
}
if ( ( sender & SENDER_TARGET ) & & ! IS_SENDER_TARGET ( param ) ) {
pr_err ( " Key \" %s \" may not be sent to %s, "
" protocol error. \n " , param - > name ,
( sender & SENDER_RECEIVER ) ? " initiator " : " target " ) ;
return NULL ;
}
return param ;
}
static struct iscsi_param * iscsi_check_key (
char * key ,
int phase ,
int sender ,
struct iscsi_param_list * param_list )
{
struct iscsi_param * param ;
/*
* Key name length must not exceed 63 bytes . ( See iSCSI v20 5.1 )
*/
if ( strlen ( key ) > KEY_MAXLEN ) {
pr_err ( " Length of key name \" %s \" exceeds %d. \n " ,
key , KEY_MAXLEN ) ;
return NULL ;
}
param = iscsi_find_param_from_key ( key , param_list ) ;
if ( ! param )
return NULL ;
if ( ( sender & SENDER_INITIATOR ) & & ! IS_SENDER_INITIATOR ( param ) ) {
pr_err ( " Key \" %s \" may not be sent to %s, "
" protocol error. \n " , param - > name ,
( sender & SENDER_RECEIVER ) ? " target " : " initiator " ) ;
return NULL ;
}
if ( ( sender & SENDER_TARGET ) & & ! IS_SENDER_TARGET ( param ) ) {
pr_err ( " Key \" %s \" may not be sent to %s, "
" protocol error. \n " , param - > name ,
( sender & SENDER_RECEIVER ) ? " initiator " : " target " ) ;
return NULL ;
}
if ( IS_PSTATE_ACCEPTOR ( param ) ) {
pr_err ( " Key \" %s \" received twice, protocol error. \n " ,
key ) ;
return NULL ;
}
if ( ! phase )
return param ;
if ( ! ( param - > phase & phase ) ) {
pr_err ( " Key \" %s \" may not be negotiated during " ,
param - > name ) ;
switch ( phase ) {
case PHASE_SECURITY :
pr_debug ( " Security phase. \n " ) ;
break ;
case PHASE_OPERATIONAL :
pr_debug ( " Operational phase. \n " ) ;
default :
pr_debug ( " Unknown phase. \n " ) ;
}
return NULL ;
}
return param ;
}
static int iscsi_enforce_integrity_rules (
u8 phase ,
struct iscsi_param_list * param_list )
{
char * tmpptr ;
u8 DataSequenceInOrder = 0 ;
u8 ErrorRecoveryLevel = 0 , SessionType = 0 ;
u8 IFMarker = 0 , OFMarker = 0 ;
2011-09-16 12:44:54 +04:00
u8 IFMarkInt_Reject = 1 , OFMarkInt_Reject = 1 ;
2011-07-23 10:43:04 +04:00
u32 FirstBurstLength = 0 , MaxBurstLength = 0 ;
struct iscsi_param * param = NULL ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! ( param - > phase & phase ) )
continue ;
if ( ! strcmp ( param - > name , SESSIONTYPE ) )
if ( ! strcmp ( param - > value , NORMAL ) )
SessionType = 1 ;
if ( ! strcmp ( param - > name , ERRORRECOVERYLEVEL ) )
ErrorRecoveryLevel = simple_strtoul ( param - > value ,
& tmpptr , 0 ) ;
if ( ! strcmp ( param - > name , DATASEQUENCEINORDER ) )
if ( ! strcmp ( param - > value , YES ) )
DataSequenceInOrder = 1 ;
if ( ! strcmp ( param - > name , MAXBURSTLENGTH ) )
MaxBurstLength = simple_strtoul ( param - > value ,
& 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 , & param_list - > param_list , p_list ) {
if ( ! ( param - > phase & phase ) )
continue ;
if ( ! SessionType & & ( ! IS_PSTATE_ACCEPTOR ( param ) & &
( strcmp ( param - > name , IFMARKER ) & &
strcmp ( param - > name , OFMARKER ) & &
strcmp ( param - > name , IFMARKINT ) & &
strcmp ( param - > name , OFMARKINT ) ) ) )
continue ;
if ( ! strcmp ( param - > name , MAXOUTSTANDINGR2T ) & &
DataSequenceInOrder & & ( ErrorRecoveryLevel > 0 ) ) {
if ( strcmp ( param - > value , " 1 " ) ) {
if ( iscsi_update_param_value ( param , " 1 " ) < 0 )
return - 1 ;
pr_debug ( " Reset \" %s \" to \" %s \" . \n " ,
param - > name , param - > value ) ;
}
}
if ( ! strcmp ( param - > name , MAXCONNECTIONS ) & & ! SessionType ) {
if ( strcmp ( param - > value , " 1 " ) ) {
if ( iscsi_update_param_value ( param , " 1 " ) < 0 )
return - 1 ;
pr_debug ( " Reset \" %s \" to \" %s \" . \n " ,
param - > name , param - > value ) ;
}
}
if ( ! strcmp ( param - > name , FIRSTBURSTLENGTH ) ) {
FirstBurstLength = simple_strtoul ( param - > value ,
& tmpptr , 0 ) ;
if ( FirstBurstLength > MaxBurstLength ) {
char tmpbuf [ 10 ] ;
memset ( tmpbuf , 0 , 10 ) ;
sprintf ( tmpbuf , " %u " , MaxBurstLength ) ;
if ( iscsi_update_param_value ( param , tmpbuf ) )
return - 1 ;
pr_debug ( " Reset \" %s \" to \" %s \" . \n " ,
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 ;
}
int iscsi_decode_text_input (
u8 phase ,
u8 sender ,
char * textbuf ,
u32 length ,
struct iscsi_param_list * param_list )
{
char * tmpbuf , * start = NULL , * end = NULL ;
tmpbuf = kzalloc ( length + 1 , GFP_KERNEL ) ;
if ( ! tmpbuf ) {
pr_err ( " Unable to allocate memory for tmpbuf. \n " ) ;
return - 1 ;
}
memcpy ( tmpbuf , textbuf , length ) ;
tmpbuf [ length ] = ' \0 ' ;
start = tmpbuf ;
end = ( start + length ) ;
while ( start < end ) {
char * key , * value ;
struct iscsi_param * param ;
if ( iscsi_extract_key_value ( start , & key , & value ) < 0 ) {
kfree ( tmpbuf ) ;
return - 1 ;
}
pr_debug ( " Got key: %s=%s \n " , key , value ) ;
if ( phase & PHASE_SECURITY ) {
if ( iscsi_check_for_auth_key ( key ) > 0 ) {
char * tmpptr = key + strlen ( key ) ;
* tmpptr = ' = ' ;
kfree ( tmpbuf ) ;
return 1 ;
}
}
param = iscsi_check_key ( key , phase , sender , param_list ) ;
if ( ! param ) {
if ( iscsi_add_notunderstood_response ( key ,
value , param_list ) < 0 ) {
kfree ( tmpbuf ) ;
return - 1 ;
}
start + = strlen ( key ) + strlen ( value ) + 2 ;
continue ;
}
if ( iscsi_check_value ( param , value ) < 0 ) {
kfree ( tmpbuf ) ;
return - 1 ;
}
start + = strlen ( key ) + strlen ( value ) + 2 ;
if ( IS_PSTATE_PROPOSER ( param ) ) {
if ( iscsi_check_proposer_state ( param , value ) < 0 ) {
kfree ( tmpbuf ) ;
return - 1 ;
}
SET_PSTATE_RESPONSE_GOT ( param ) ;
} else {
if ( iscsi_check_acceptor_state ( param , value ) < 0 ) {
kfree ( tmpbuf ) ;
return - 1 ;
}
SET_PSTATE_ACCEPTOR ( param ) ;
}
}
kfree ( tmpbuf ) ;
return 0 ;
}
int iscsi_encode_text_output (
u8 phase ,
u8 sender ,
char * textbuf ,
u32 * length ,
struct iscsi_param_list * param_list )
{
char * output_buf = NULL ;
struct iscsi_extra_response * er ;
struct iscsi_param * param ;
output_buf = textbuf + * length ;
if ( iscsi_enforce_integrity_rules ( phase , param_list ) < 0 )
return - 1 ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! ( param - > sender & sender ) )
continue ;
if ( IS_PSTATE_ACCEPTOR ( param ) & &
! IS_PSTATE_RESPONSE_SENT ( param ) & &
! IS_PSTATE_REPLY_OPTIONAL ( param ) & &
( param - > phase & phase ) ) {
* length + = sprintf ( output_buf , " %s=%s " ,
param - > name , param - > value ) ;
* length + = 1 ;
output_buf = textbuf + * length ;
SET_PSTATE_RESPONSE_SENT ( param ) ;
pr_debug ( " Sending key: %s=%s \n " ,
param - > name , param - > value ) ;
continue ;
}
if ( IS_PSTATE_NEGOTIATE ( param ) & &
! IS_PSTATE_ACCEPTOR ( param ) & &
! IS_PSTATE_PROPOSER ( param ) & &
( param - > phase & phase ) ) {
* length + = sprintf ( output_buf , " %s=%s " ,
param - > name , param - > value ) ;
* length + = 1 ;
output_buf = textbuf + * length ;
SET_PSTATE_PROPOSER ( param ) ;
iscsi_check_proposer_for_optional_reply ( param ) ;
pr_debug ( " Sending key: %s=%s \n " ,
param - > name , param - > value ) ;
}
}
list_for_each_entry ( er , & param_list - > extra_response_list , er_list ) {
* length + = sprintf ( output_buf , " %s=%s " , er - > key , er - > value ) ;
* length + = 1 ;
output_buf = textbuf + * length ;
pr_debug ( " Sending key: %s=%s \n " , er - > key , er - > value ) ;
}
iscsi_release_extra_responses ( param_list ) ;
return 0 ;
}
int iscsi_check_negotiated_keys ( struct iscsi_param_list * param_list )
{
int ret = 0 ;
struct iscsi_param * param ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( IS_PSTATE_NEGOTIATE ( param ) & &
IS_PSTATE_PROPOSER ( param ) & &
! IS_PSTATE_RESPONSE_GOT ( param ) & &
! IS_PSTATE_REPLY_OPTIONAL ( param ) & &
! IS_PHASE_DECLARATIVE ( param ) ) {
pr_err ( " No response for proposed key \" %s \" . \n " ,
param - > name ) ;
ret = - 1 ;
}
}
return ret ;
}
int iscsi_change_param_value (
char * keyvalue ,
struct iscsi_param_list * param_list ,
int check_key )
{
char * key = NULL , * value = NULL ;
struct iscsi_param * param ;
int sender = 0 ;
if ( iscsi_extract_key_value ( keyvalue , & key , & value ) < 0 )
return - 1 ;
if ( ! check_key ) {
param = __iscsi_check_key ( keyvalue , sender , param_list ) ;
if ( ! param )
return - 1 ;
} else {
param = iscsi_check_key ( keyvalue , 0 , sender , param_list ) ;
if ( ! param )
return - 1 ;
param - > set_param = 1 ;
if ( iscsi_check_value ( param , value ) < 0 ) {
param - > set_param = 0 ;
return - 1 ;
}
param - > set_param = 0 ;
}
if ( iscsi_update_param_value ( param , value ) < 0 )
return - 1 ;
return 0 ;
}
void iscsi_set_connection_parameters (
struct iscsi_conn_ops * ops ,
struct iscsi_param_list * param_list )
{
char * tmpptr ;
struct iscsi_param * param ;
pr_debug ( " --------------------------------------------------- "
" --------------- \n " ) ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! IS_PSTATE_ACCEPTOR ( param ) & & ! IS_PSTATE_PROPOSER ( param ) )
continue ;
if ( ! strcmp ( param - > name , AUTHMETHOD ) ) {
pr_debug ( " AuthMethod: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , HEADERDIGEST ) ) {
ops - > HeaderDigest = ! strcmp ( param - > value , CRC32C ) ;
pr_debug ( " HeaderDigest: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , DATADIGEST ) ) {
ops - > DataDigest = ! strcmp ( param - > value , CRC32C ) ;
pr_debug ( " DataDigest: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , MAXRECVDATASEGMENTLENGTH ) ) {
ops - > MaxRecvDataSegmentLength =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " MaxRecvDataSegmentLength: %s \n " ,
param - > value ) ;
} 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 ) ;
}
}
pr_debug ( " ---------------------------------------------------- "
" -------------- \n " ) ;
}
void iscsi_set_session_parameters (
struct iscsi_sess_ops * ops ,
struct iscsi_param_list * param_list ,
int leading )
{
char * tmpptr ;
struct iscsi_param * param ;
pr_debug ( " ---------------------------------------------------- "
" -------------- \n " ) ;
list_for_each_entry ( param , & param_list - > param_list , p_list ) {
if ( ! IS_PSTATE_ACCEPTOR ( param ) & & ! IS_PSTATE_PROPOSER ( param ) )
continue ;
if ( ! strcmp ( param - > name , INITIATORNAME ) ) {
if ( ! param - > value )
continue ;
if ( leading )
snprintf ( ops - > InitiatorName ,
sizeof ( ops - > InitiatorName ) ,
" %s " , param - > value ) ;
pr_debug ( " InitiatorName: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , INITIATORALIAS ) ) {
if ( ! param - > value )
continue ;
snprintf ( ops - > InitiatorAlias ,
sizeof ( ops - > InitiatorAlias ) ,
" %s " , param - > value ) ;
pr_debug ( " InitiatorAlias: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , TARGETNAME ) ) {
if ( ! param - > value )
continue ;
if ( leading )
snprintf ( ops - > TargetName ,
sizeof ( ops - > TargetName ) ,
" %s " , param - > value ) ;
pr_debug ( " TargetName: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , TARGETALIAS ) ) {
if ( ! param - > value )
continue ;
snprintf ( ops - > TargetAlias , sizeof ( ops - > TargetAlias ) ,
" %s " , param - > value ) ;
pr_debug ( " TargetAlias: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , TARGETPORTALGROUPTAG ) ) {
ops - > TargetPortalGroupTag =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " TargetPortalGroupTag: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , MAXCONNECTIONS ) ) {
ops - > MaxConnections =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " MaxConnections: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , INITIALR2T ) ) {
ops - > InitialR2T = ! strcmp ( param - > value , YES ) ;
pr_debug ( " InitialR2T: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , IMMEDIATEDATA ) ) {
ops - > ImmediateData = ! strcmp ( param - > value , YES ) ;
pr_debug ( " ImmediateData: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , MAXBURSTLENGTH ) ) {
ops - > MaxBurstLength =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " MaxBurstLength: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , FIRSTBURSTLENGTH ) ) {
ops - > FirstBurstLength =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " FirstBurstLength: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , DEFAULTTIME2WAIT ) ) {
ops - > DefaultTime2Wait =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " DefaultTime2Wait: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , DEFAULTTIME2RETAIN ) ) {
ops - > DefaultTime2Retain =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " DefaultTime2Retain: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , MAXOUTSTANDINGR2T ) ) {
ops - > MaxOutstandingR2T =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " MaxOutstandingR2T: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , DATAPDUINORDER ) ) {
ops - > DataPDUInOrder = ! strcmp ( param - > value , YES ) ;
pr_debug ( " DataPDUInOrder: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , DATASEQUENCEINORDER ) ) {
ops - > DataSequenceInOrder = ! strcmp ( param - > value , YES ) ;
pr_debug ( " DataSequenceInOrder: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , ERRORRECOVERYLEVEL ) ) {
ops - > ErrorRecoveryLevel =
simple_strtoul ( param - > value , & tmpptr , 0 ) ;
pr_debug ( " ErrorRecoveryLevel: %s \n " ,
param - > value ) ;
} else if ( ! strcmp ( param - > name , SESSIONTYPE ) ) {
ops - > SessionType = ! strcmp ( param - > value , DISCOVERY ) ;
pr_debug ( " SessionType: %s \n " ,
param - > value ) ;
}
}
pr_debug ( " ---------------------------------------------------- "
" -------------- \n " ) ;
}