iscsi.c File Reference

iSCSI protocol More...

#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <gpxe/vsprintf.h>
#include <gpxe/socket.h>
#include <gpxe/xfer.h>
#include <gpxe/open.h>
#include <gpxe/scsi.h>
#include <gpxe/process.h>
#include <gpxe/uaccess.h>
#include <gpxe/tcpip.h>
#include <gpxe/settings.h>
#include <gpxe/features.h>
#include <gpxe/iscsi.h>

Go to the source code of this file.

Data Structures

struct  iscsi_string_type
 An iSCSI text string that we want to handle. More...
struct  iscsi_string_setting
 An iSCSI string setting. More...

Defines

#define EACCES_INCORRECT_TARGET_USERNAME   ( EACCES | EUNIQ_01 )
#define EACCES_INCORRECT_TARGET_PASSWORD   ( EACCES | EUNIQ_02 )
#define ENOTSUP_INITIATOR_STATUS   ( ENOTSUP | EUNIQ_01 )
#define ENOTSUP_OPCODE   ( ENOTSUP | EUNIQ_02 )
#define ENOTSUP_DISCOVERY   ( ENOTSUP | EUNIQ_03 )
#define EPERM_INITIATOR_AUTHENTICATION   ( EPERM | EUNIQ_01 )
#define EPERM_INITIATOR_AUTHORISATION   ( EPERM | EUNIQ_02 )
#define EPROTO_INVALID_CHAP_ALGORITHM   ( EPROTO | EUNIQ_01 )
#define EPROTO_INVALID_CHAP_IDENTIFIER   ( EPROTO | EUNIQ_02 )
#define EPROTO_INVALID_CHAP_CHALLENGE   ( EPROTO | EUNIQ_03 )
#define EPROTO_INVALID_CHAP_RESPONSE   ( EPROTO | EUNIQ_04 )

Enumerations

enum  iscsi_root_path_component {
  RP_LITERAL = 0, RP_SERVERNAME, RP_PROTOCOL, RP_PORT,
  RP_LUN, RP_TARGETNAME, NUM_RP_COMPONENTS
}
 iSCSI root path components (as per RFC4173) More...

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FEATURE (FEATURE_PROTOCOL,"iSCSI", DHCP_EB_FEATURE_ISCSI, 1)
static void iscsi_start_tx (struct iscsi_session *iscsi)
 Start up a new TX PDU.
static void iscsi_start_login (struct iscsi_session *iscsi)
 Build iSCSI login request BHS.
static void iscsi_start_data_out (struct iscsi_session *iscsi, unsigned int datasn)
 Build iSCSI data-out BHS.
static void iscsi_rx_buffered_data_done (struct iscsi_session *iscsi)
 Finish receiving PDU data into buffer.
static void iscsi_free (struct refcnt *refcnt)
 Free iSCSI session.
static int iscsi_open_connection (struct iscsi_session *iscsi)
 Open iSCSI transport-layer connection.
static void iscsi_close_connection (struct iscsi_session *iscsi, int rc)
 Close iSCSI transport-layer connection.
static void iscsi_scsi_done (struct iscsi_session *iscsi, int rc)
 Mark iSCSI SCSI operation as complete.
static void iscsi_start_command (struct iscsi_session *iscsi)
 Build iSCSI SCSI command BHS.
static int iscsi_rx_scsi_response (struct iscsi_session *iscsi, const void *data, size_t len, size_t remaining)
 Receive data segment of an iSCSI SCSI response PDU.
static int iscsi_rx_data_in (struct iscsi_session *iscsi, const void *data, size_t len, size_t remaining)
 Receive data segment of an iSCSI data-in PDU.
static int iscsi_rx_r2t (struct iscsi_session *iscsi, const void *data __unused, size_t len __unused, size_t remaining __unused)
 Receive data segment of an iSCSI R2T PDU.
static void iscsi_data_out_done (struct iscsi_session *iscsi)
 Complete iSCSI data-out PDU transmission.
static int iscsi_tx_data_out (struct iscsi_session *iscsi)
 Send iSCSI data-out data segment.
static int iscsi_build_login_request_strings (struct iscsi_session *iscsi, void *data, size_t len)
 Build iSCSI login request strings.
static void iscsi_login_request_done (struct iscsi_session *iscsi)
 Complete iSCSI login request PDU transmission.
static int iscsi_tx_login_request (struct iscsi_session *iscsi)
 Transmit data segment of an iSCSI login request PDU.
static int iscsi_handle_targetaddress_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI TargetAddress text value.
static int iscsi_handle_authmethod_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI AuthMethod text value.
static int iscsi_handle_chap_a_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI CHAP_A text value.
static int iscsi_handle_chap_i_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI CHAP_I text value.
static int iscsi_handle_chap_c_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI CHAP_C text value.
static int iscsi_handle_chap_n_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI CHAP_N text value.
static int iscsi_handle_chap_r_value (struct iscsi_session *iscsi, const char *value)
 Handle iSCSI CHAP_R text value.
static int iscsi_handle_string (struct iscsi_session *iscsi, const char *string)
 Handle iSCSI string.
static int iscsi_handle_strings (struct iscsi_session *iscsi, const char *strings, size_t len)
 Handle iSCSI strings.
static int iscsi_rx_buffered_data (struct iscsi_session *iscsi, const void *data, size_t len)
 Receive PDU data into buffer.
static int iscsi_status_to_rc (unsigned int status_class, unsigned int status_detail)
 Convert iSCSI response status to return status code.
static int iscsi_rx_login_response (struct iscsi_session *iscsi, const void *data, size_t len, size_t remaining)
 Receive data segment of an iSCSI login response PDU.
static int iscsi_tx_nothing (struct iscsi_session *iscsi __unused)
 Transmit nothing.
static int iscsi_tx_bhs (struct iscsi_session *iscsi)
 Transmit basic header segment of an iSCSI PDU.
static int iscsi_tx_data (struct iscsi_session *iscsi)
 Transmit data segment of an iSCSI PDU.
static int iscsi_tx_data_padding (struct iscsi_session *iscsi)
 Transmit data padding of an iSCSI PDU.
static void iscsi_tx_done (struct iscsi_session *iscsi)
 Complete iSCSI PDU transmission.
static void iscsi_tx_step (struct process *process)
 Transmit iSCSI PDU.
static int iscsi_rx_bhs (struct iscsi_session *iscsi, const void *data, size_t len, size_t remaining __unused)
 Receive basic header segment of an iSCSI PDU.
static int iscsi_rx_discard (struct iscsi_session *iscsi __unused, const void *data __unused, size_t len __unused, size_t remaining __unused)
 Discard portion of an iSCSI PDU.
static int iscsi_rx_data (struct iscsi_session *iscsi, const void *data, size_t len, size_t remaining)
 Receive data segment of an iSCSI PDU.
static int iscsi_socket_deliver_raw (struct xfer_interface *socket, const void *data, size_t len)
 Receive new data.
static void iscsi_socket_close (struct xfer_interface *socket, int rc)
 Handle stream connection closure.
static int iscsi_vredirect (struct xfer_interface *socket, int type, va_list args)
 Handle redirection event.
static int iscsi_command (struct scsi_device *scsi, struct scsi_command *command)
 Issue SCSI command.
void iscsi_detach (struct scsi_device *scsi)
 Shut down iSCSI interface.
static int iscsi_parse_root_path (struct iscsi_session *iscsi, const char *root_path)
 Parse iSCSI root path.
static int iscsi_set_auth (struct iscsi_session *iscsi, const char *initiator_username, const char *initiator_password, const char *target_username, const char *target_password)
 Set iSCSI authentication details.
int iscsi_attach (struct scsi_device *scsi, const char *root_path)
 Attach iSCSI interface.
static int apply_iscsi_string_setting (struct iscsi_string_setting *setting)
 Apply iSCSI setting.
static int apply_iscsi_settings (void)
 Apply iSCSI settings.
const char * iscsi_initiator_iqn (void)
 Get iSCSI initiator IQN.

Variables

static char * iscsi_explicit_initiator_iqn
 iSCSI initiator name (explicitly specified)
static char * iscsi_default_initiator_iqn
 Default iSCSI initiator name (constructed from hostname).
static char * iscsi_initiator_username
 iSCSI initiator username
static char * iscsi_initiator_password
 iSCSI initiator password
static char * iscsi_target_username
 iSCSI target username
static char * iscsi_target_password
 iSCSI target password
static struct iscsi_string_type iscsi_string_types []
 iSCSI text strings that we want to handle
static struct
xfer_interface_operations 
iscsi_socket_operations
 iSCSI socket operations
struct setting
initiator_iqn_setting 
__setting
 iSCSI initiator IQN setting
static struct iscsi_string_setting iscsi_string_settings []
 iSCSI string settings
struct settings_applicator
iscsi_settings_applicator 
__settings_applicator
 iSCSI settings applicator


Detailed Description

iSCSI protocol

Definition in file iscsi.c.


Define Documentation

#define EACCES_INCORRECT_TARGET_USERNAME   ( EACCES | EUNIQ_01 )

Definition at line 49 of file iscsi.c.

Referenced by iscsi_handle_chap_n_value().

#define EACCES_INCORRECT_TARGET_PASSWORD   ( EACCES | EUNIQ_02 )

Definition at line 50 of file iscsi.c.

Referenced by iscsi_handle_chap_r_value().

#define ENOTSUP_INITIATOR_STATUS   ( ENOTSUP | EUNIQ_01 )

Definition at line 51 of file iscsi.c.

Referenced by iscsi_status_to_rc().

#define ENOTSUP_OPCODE   ( ENOTSUP | EUNIQ_02 )

Definition at line 52 of file iscsi.c.

Referenced by iscsi_rx_data().

#define ENOTSUP_DISCOVERY   ( ENOTSUP | EUNIQ_03 )

Definition at line 53 of file iscsi.c.

Referenced by iscsi_attach().

#define EPERM_INITIATOR_AUTHENTICATION   ( EPERM | EUNIQ_01 )

Definition at line 54 of file iscsi.c.

Referenced by iscsi_status_to_rc().

#define EPERM_INITIATOR_AUTHORISATION   ( EPERM | EUNIQ_02 )

Definition at line 55 of file iscsi.c.

Referenced by iscsi_status_to_rc().

#define EPROTO_INVALID_CHAP_ALGORITHM   ( EPROTO | EUNIQ_01 )

Definition at line 56 of file iscsi.c.

Referenced by iscsi_handle_chap_a_value().

#define EPROTO_INVALID_CHAP_IDENTIFIER   ( EPROTO | EUNIQ_02 )

Definition at line 57 of file iscsi.c.

Referenced by iscsi_handle_chap_i_value().

#define EPROTO_INVALID_CHAP_CHALLENGE   ( EPROTO | EUNIQ_03 )

Definition at line 58 of file iscsi.c.

Referenced by iscsi_handle_chap_c_value().

#define EPROTO_INVALID_CHAP_RESPONSE   ( EPROTO | EUNIQ_04 )

Definition at line 59 of file iscsi.c.

Referenced by iscsi_handle_chap_r_value().


Enumeration Type Documentation

iSCSI root path components (as per RFC4173)

Enumerator:
RP_LITERAL 
RP_SERVERNAME 
RP_PROTOCOL 
RP_PORT 
RP_LUN 
RP_TARGETNAME 
NUM_RP_COMPONENTS 

Definition at line 1618 of file iscsi.c.

01618                                {
01619         RP_LITERAL = 0,
01620         RP_SERVERNAME,
01621         RP_PROTOCOL,
01622         RP_PORT,
01623         RP_LUN,
01624         RP_TARGETNAME,
01625         NUM_RP_COMPONENTS
01626 };


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

FEATURE ( FEATURE_PROTOCOL  ,
"iSCSI"  ,
DHCP_EB_FEATURE_ISCSI  ,
 
)

static void iscsi_start_tx ( struct iscsi_session iscsi  )  [static]

Start up a new TX PDU.

Parameters:
iscsi iSCSI session
This initiates the process of sending a new PDU. Only one PDU may be in transit at any one time.

Definition at line 1147 of file iscsi.c.

References assert, ISCSI_TX_BHS, ISCSI_TX_IDLE, memset(), iscsi_session::tx_bhs, and iscsi_session::tx_state.

Referenced by iscsi_start_command(), iscsi_start_data_out(), and iscsi_start_login().

01147                                                            {
01148         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
01149         
01150         /* Initialise TX BHS */
01151         memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
01152 
01153         /* Flag TX engine to start transmitting */
01154         iscsi->tx_state = ISCSI_TX_BHS;
01155 }

static void iscsi_start_login ( struct iscsi_session iscsi  )  [static]

Build iSCSI login request BHS.

Parameters:
iscsi iSCSI session

Definition at line 559 of file iscsi.c.

References iscsi_session::cmdsn, iscsi_bhs_login_request::cmdsn, iscsi_bhs_login_request::expstatsn, iscsi_bhs_login_request::flags, htonl, htons, IANA_EN_FEN_SYSTEMS, iscsi_build_login_request_strings(), ISCSI_FLAG_IMMEDIATE, ISCSI_ISID_IANA, ISCSI_LOGIN_FLAG_TRANSITION, ISCSI_OPCODE_LOGIN_REQUEST, ISCSI_SET_LENGTHS, iscsi_start_tx(), ISCSI_STATUS_PHASE_MASK, iscsi_bhs_login_request::isid_iana_en, iscsi_session::itt, iscsi_bhs_login_request::itt, iscsi_bhs_login_request::lengths, iscsi_bhs::login_request, NULL, iscsi_bhs_login_request::opcode, iscsi_session::statsn, iscsi_session::status, iscsi_session::tsih, iscsi_bhs_login_request::tsih, and iscsi_session::tx_bhs.

Referenced by iscsi_open_connection(), and iscsi_rx_login_response().

00559                                                               {
00560         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
00561         int len;
00562 
00563         /* Construct BHS and initiate transmission */
00564         iscsi_start_tx ( iscsi );
00565         request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
00566                             ISCSI_FLAG_IMMEDIATE );
00567         request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
00568                            ISCSI_LOGIN_FLAG_TRANSITION );
00569         /* version_max and version_min left as zero */
00570         len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
00571         ISCSI_SET_LENGTHS ( request->lengths, 0, len );
00572         request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
00573                                         IANA_EN_FEN_SYSTEMS );
00574         /* isid_iana_qual left as zero */
00575         request->tsih = htons ( iscsi->tsih );
00576         request->itt = htonl ( iscsi->itt );
00577         /* cid left as zero */
00578         request->cmdsn = htonl ( iscsi->cmdsn );
00579         request->expstatsn = htonl ( iscsi->statsn + 1 );
00580 }

static void iscsi_start_data_out ( struct iscsi_session iscsi,
unsigned int  datasn 
) [static]

Build iSCSI data-out BHS.

Parameters:
iscsi iSCSI session
datasn Data sequence number within the transfer

Definition at line 357 of file iscsi.c.

References iscsi_bhs::data_out, iscsi_bhs_data_out::datasn, DBGC, iscsi_bhs_data_out::expstatsn, iscsi_bhs_data_out::flags, htonl, ISCSI_FLAG_FINAL, ISCSI_OPCODE_DATA_OUT, ISCSI_SET_LENGTHS, iscsi_start_tx(), iscsi_session::itt, iscsi_bhs_data_out::itt, iscsi_bhs_data_out::lengths, iscsi_session::lun, iscsi_bhs_data_out::lun, iscsi_bhs_data_out::offset, offset, iscsi_bhs_data_out::opcode, iscsi_session::statsn, iscsi_session::transfer_len, iscsi_session::transfer_offset, iscsi_session::ttt, iscsi_bhs_data_out::ttt, and iscsi_session::tx_bhs.

Referenced by iscsi_data_out_done(), and iscsi_rx_r2t().

00358                                                          {
00359         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
00360         unsigned long offset;
00361         unsigned long remaining;
00362         unsigned long len;
00363 
00364         /* We always send 512-byte Data-Out PDUs; this removes the
00365          * need to worry about the target's MaxRecvDataSegmentLength.
00366          */
00367         offset = datasn * 512;
00368         remaining = iscsi->transfer_len - offset;
00369         len = remaining;
00370         if ( len > 512 )
00371                 len = 512;
00372 
00373         /* Construct BHS and initiate transmission */
00374         iscsi_start_tx ( iscsi );
00375         data_out->opcode = ISCSI_OPCODE_DATA_OUT;
00376         if ( len == remaining )
00377                 data_out->flags = ( ISCSI_FLAG_FINAL );
00378         ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
00379         data_out->lun = iscsi->lun;
00380         data_out->itt = htonl ( iscsi->itt );
00381         data_out->ttt = htonl ( iscsi->ttt );
00382         data_out->expstatsn = htonl ( iscsi->statsn + 1 );
00383         data_out->datasn = htonl ( datasn );
00384         data_out->offset = htonl ( iscsi->transfer_offset + offset );
00385         DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
00386                iscsi, datasn, len );
00387 }

static void iscsi_rx_buffered_data_done ( struct iscsi_session iscsi  )  [static]

Finish receiving PDU data into buffer.

Parameters:
iscsi iSCSI session

Definition at line 89 of file iscsi.c.

References free(), NULL, and iscsi_session::rx_buffer.

Referenced by iscsi_close_connection(), iscsi_free(), and iscsi_rx_login_response().

00089                                                                         {
00090         free ( iscsi->rx_buffer );
00091         iscsi->rx_buffer = NULL;
00092 }

static void iscsi_free ( struct refcnt refcnt  )  [static]

Free iSCSI session.

Parameters:
refcnt Reference counter

Definition at line 99 of file iscsi.c.

References iscsi_session::chap, chap_finish(), container_of, free(), iscsi_session::initiator_password, iscsi_session::initiator_username, iscsi_rx_buffered_data_done(), iscsi_session::target_address, iscsi_session::target_iqn, iscsi_session::target_password, and iscsi_session::target_username.

Referenced by iscsi_attach().

00099                                                  {
00100         struct iscsi_session *iscsi =
00101                 container_of ( refcnt, struct iscsi_session, refcnt );
00102 
00103         free ( iscsi->target_address );
00104         free ( iscsi->target_iqn );
00105         free ( iscsi->initiator_username );
00106         free ( iscsi->initiator_password );
00107         free ( iscsi->target_username );
00108         free ( iscsi->target_password );
00109         chap_finish ( &iscsi->chap );
00110         iscsi_rx_buffered_data_done ( iscsi );
00111         free ( iscsi );
00112 }

static int iscsi_open_connection ( struct iscsi_session iscsi  )  [static]

Open iSCSI transport-layer connection.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code

Definition at line 120 of file iscsi.c.

References assert, DBGC, htons, ISCSI_RX_BHS, iscsi_start_login(), ISCSI_STATUS_AUTH_REVERSE_REQUIRED, ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE, ISCSI_STATUS_STRINGS_SECURITY, ISCSI_TX_IDLE, iscsi_session::itt, memset(), NULL, iscsi_session::rx_offset, iscsi_session::rx_state, SOCK_STREAM, iscsi_session::socket, sockaddr_tcpip::st_port, iscsi_session::status, strerror(), iscsi_session::target_address, iscsi_session::target_port, iscsi_session::target_username, iscsi_session::tx_state, and xfer_open_named_socket().

Referenced by iscsi_command(), iscsi_rx_login_response(), and iscsi_socket_close().

00120                                                                  {
00121         struct sockaddr_tcpip target;
00122         int rc;
00123 
00124         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
00125         assert ( iscsi->rx_state == ISCSI_RX_BHS );
00126         assert ( iscsi->rx_offset == 0 );
00127 
00128         /* Open socket */
00129         memset ( &target, 0, sizeof ( target ) );
00130         target.st_port = htons ( iscsi->target_port );
00131         if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
00132                                              ( struct sockaddr * ) &target,
00133                                              iscsi->target_address,
00134                                              NULL ) ) != 0 ) {
00135                 DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
00136                        iscsi, strerror ( rc ) );
00137                 return rc;
00138         }
00139 
00140         /* Enter security negotiation phase */
00141         iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
00142                           ISCSI_STATUS_STRINGS_SECURITY );
00143         if ( iscsi->target_username )
00144                 iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
00145 
00146         /* Assign fresh initiator task tag */
00147         iscsi->itt++;
00148 
00149         /* Initiate login */
00150         iscsi_start_login ( iscsi );
00151 
00152         return 0;
00153 }

static void iscsi_close_connection ( struct iscsi_session iscsi,
int  rc 
) [static]

Close iSCSI transport-layer connection.

Parameters:
iscsi iSCSI session
rc Reason for close
Closes the transport-layer connection and resets the session state ready to attempt a fresh login.

Definition at line 164 of file iscsi.c.

References iscsi_session::chap, chap_finish(), ISCSI_RX_BHS, iscsi_rx_buffered_data_done(), ISCSI_TX_IDLE, iscsi_session::rx_offset, iscsi_session::rx_state, iscsi_session::socket, iscsi_session::status, iscsi_session::tx_state, and xfer_close().

Referenced by iscsi_detach(), iscsi_rx_login_response(), iscsi_socket_close(), and iscsi_socket_deliver_raw().

00164                                                                            {
00165 
00166         /* Close all data transfer interfaces */
00167         xfer_close ( &iscsi->socket, rc );
00168 
00169         /* Clear connection status */
00170         iscsi->status = 0;
00171 
00172         /* Reset TX and RX state machines */
00173         iscsi->tx_state = ISCSI_TX_IDLE;
00174         iscsi->rx_state = ISCSI_RX_BHS;
00175         iscsi->rx_offset = 0;
00176 
00177         /* Free any temporary dynamically allocated memory */
00178         chap_finish ( &iscsi->chap );
00179         iscsi_rx_buffered_data_done ( iscsi );
00180 }

static void iscsi_scsi_done ( struct iscsi_session iscsi,
int  rc 
) [static]

Mark iSCSI SCSI operation as complete.

Parameters:
iscsi iSCSI session
rc Return status code
Note that iscsi_scsi_done() will not close the connection, and must therefore be called only when the internal state machines are in an appropriate state, otherwise bad things may happen on the next call to iscsi_issue(). The general rule is to call iscsi_scsi_done() only at the end of receiving a PDU; at this point the TX and RX engines should both be idle.

Definition at line 195 of file iscsi.c.

References assert, iscsi_session::command, ISCSI_TX_IDLE, NULL, scsi_command::rc, and iscsi_session::tx_state.

Referenced by iscsi_rx_data_in(), iscsi_rx_scsi_response(), iscsi_socket_close(), and iscsi_socket_deliver_raw().

00195                                                                     {
00196 
00197         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
00198         assert ( iscsi->command != NULL );
00199 
00200         iscsi->command->rc = rc;
00201         iscsi->command = NULL;
00202 }

static void iscsi_start_command ( struct iscsi_session iscsi  )  [static]

Build iSCSI SCSI command BHS.

Parameters:
iscsi iSCSI session
We don't currently support bidirectional commands (i.e. with both Data-In and Data-Out segments); these would require providing code to generate an AHS, and there doesn't seem to be any need for it at the moment.

Definition at line 220 of file iscsi.c.

References assert, scsi_command::cdb, iscsi_bhs_scsi_command::cdb, iscsi_session::cmdsn, iscsi_bhs_scsi_command::cmdsn, iscsi_session::command, scsi_command::data_in, scsi_command::data_in_len, scsi_command::data_out, scsi_command::data_out_len, DBGC2, iscsi_bhs_scsi_command::exp_len, iscsi_bhs_scsi_command::expstatsn, iscsi_bhs_scsi_command::flags, htonl, ISCSI_COMMAND_ATTR_SIMPLE, ISCSI_COMMAND_FLAG_READ, ISCSI_COMMAND_FLAG_WRITE, ISCSI_FLAG_FINAL, ISCSI_OPCODE_SCSI_COMMAND, iscsi_start_tx(), iscsi_session::itt, iscsi_bhs_scsi_command::itt, iscsi_session::lun, iscsi_bhs_scsi_command::lun, memcpy, iscsi_bhs_scsi_command::opcode, SCSI_CDB_DATA, SCSI_CDB_FORMAT, iscsi_bhs::scsi_command, iscsi_session::statsn, and iscsi_session::tx_bhs.

Referenced by iscsi_command(), and iscsi_rx_login_response().

00220                                                                 {
00221         struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
00222 
00223         assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
00224 
00225         /* Construct BHS and initiate transmission */
00226         iscsi_start_tx ( iscsi );
00227         command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
00228         command->flags = ( ISCSI_FLAG_FINAL |
00229                            ISCSI_COMMAND_ATTR_SIMPLE );
00230         if ( iscsi->command->data_in )
00231                 command->flags |= ISCSI_COMMAND_FLAG_READ;
00232         if ( iscsi->command->data_out )
00233                 command->flags |= ISCSI_COMMAND_FLAG_WRITE;
00234         /* lengths left as zero */
00235         command->lun = iscsi->lun;
00236         command->itt = htonl ( ++iscsi->itt );
00237         command->exp_len = htonl ( iscsi->command->data_in_len |
00238                                    iscsi->command->data_out_len );
00239         command->cmdsn = htonl ( iscsi->cmdsn );
00240         command->expstatsn = htonl ( iscsi->statsn + 1 );
00241         memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
00242         DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
00243                 iscsi, SCSI_CDB_DATA ( command->cdb ),
00244                 ( iscsi->command->data_in ? "in" : "out" ),
00245                 ( iscsi->command->data_in ?
00246                   iscsi->command->data_in_len :
00247                   iscsi->command->data_out_len ) );
00248 }

static int iscsi_rx_scsi_response ( struct iscsi_session iscsi,
const void *  data,
size_t  len,
size_t  remaining 
) [static]

Receive data segment of an iSCSI SCSI response PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code

Definition at line 259 of file iscsi.c.

References iscsi_session::command, EIO, ISCSI_RESPONSE_COMMAND_COMPLETE, iscsi_scsi_done(), ISCSI_SENSE_RESPONSE_CODE_OFFSET, iscsi_bhs_scsi_response::response, iscsi_session::rx_bhs, iscsi_session::rx_offset, iscsi_bhs::scsi_response, scsi_command::sense_response, iscsi_bhs_scsi_response::status, and scsi_command::status.

Referenced by iscsi_rx_data().

00261                                                        {
00262         struct iscsi_bhs_scsi_response *response
00263                 = &iscsi->rx_bhs.scsi_response;
00264         int sense_offset;
00265 
00266         /* Capture the sense response code as it floats past, if present */
00267         sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
00268         if ( ( sense_offset >= 0 ) && len ) {
00269                 iscsi->command->sense_response =
00270                         * ( ( char * ) data + sense_offset );
00271         }
00272 
00273         /* Wait for whole SCSI response to arrive */
00274         if ( remaining )
00275                 return 0;
00276         
00277         /* Record SCSI status code */
00278         iscsi->command->status = response->status;
00279 
00280         /* Check for errors */
00281         if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
00282                 return -EIO;
00283 
00284         /* Mark as completed */
00285         iscsi_scsi_done ( iscsi, 0 );
00286         return 0;
00287 }

static int iscsi_rx_data_in ( struct iscsi_session iscsi,
const void *  data,
size_t  len,
size_t  remaining 
) [static]

Receive data segment of an iSCSI data-in PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code

Definition at line 298 of file iscsi.c.

References assert, iscsi_session::command, copy_to_user(), scsi_command::data_in, iscsi_bhs::data_in, scsi_command::data_in_len, iscsi_bhs_data_in::flags, ISCSI_DATA_FLAG_STATUS, ISCSI_FLAG_FINAL, iscsi_scsi_done(), ntohl, NULL, iscsi_bhs_data_in::offset, offset, iscsi_session::rx_bhs, iscsi_session::rx_offset, iscsi_bhs_data_in::status, and scsi_command::status.

Referenced by iscsi_rx_data().

00300                                                  {
00301         struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
00302         unsigned long offset;
00303 
00304         /* Copy data to data-in buffer */
00305         offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
00306         assert ( iscsi->command != NULL );
00307         assert ( iscsi->command->data_in );
00308         assert ( ( offset + len ) <= iscsi->command->data_in_len );
00309         copy_to_user ( iscsi->command->data_in, offset, data, len );
00310 
00311         /* Wait for whole SCSI response to arrive */
00312         if ( remaining )
00313                 return 0;
00314 
00315         /* Mark as completed if status is present */
00316         if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
00317                 assert ( ( offset + len ) == iscsi->command->data_in_len );
00318                 assert ( data_in->flags & ISCSI_FLAG_FINAL );
00319                 iscsi->command->status = data_in->status;
00320                 /* iSCSI cannot return an error status via a data-in */
00321                 iscsi_scsi_done ( iscsi, 0 );
00322         }
00323 
00324         return 0;
00325 }

static int iscsi_rx_r2t ( struct iscsi_session iscsi,
const void *data  __unused,
size_t len  __unused,
size_t remaining  __unused 
) [static]

Receive data segment of an iSCSI R2T PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code

Definition at line 336 of file iscsi.c.

References iscsi_start_data_out(), iscsi_bhs_r2t::len, ntohl, iscsi_bhs_r2t::offset, iscsi_bhs::r2t, iscsi_session::rx_bhs, iscsi_session::transfer_len, iscsi_session::transfer_offset, iscsi_bhs_r2t::ttt, and iscsi_session::ttt.

Referenced by iscsi_rx_data().

00338                                                       {
00339         struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
00340 
00341         /* Record transfer parameters and trigger first data-out */
00342         iscsi->ttt = ntohl ( r2t->ttt );
00343         iscsi->transfer_offset = ntohl ( r2t->offset );
00344         iscsi->transfer_len = ntohl ( r2t->len );
00345         iscsi_start_data_out ( iscsi, 0 );
00346 
00347         return 0;
00348 }

static void iscsi_data_out_done ( struct iscsi_session iscsi  )  [static]

Complete iSCSI data-out PDU transmission.

Parameters:
iscsi iSCSI session

Definition at line 395 of file iscsi.c.

References iscsi_bhs::data_out, iscsi_bhs_data_out::datasn, iscsi_bhs_data_out::flags, ISCSI_FLAG_FINAL, iscsi_start_data_out(), ntohl, and iscsi_session::tx_bhs.

Referenced by iscsi_tx_done().

00395                                                                 {
00396         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
00397 
00398         /* If we haven't reached the end of the sequence, start
00399          * sending the next data-out PDU.
00400          */
00401         if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
00402                 iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
00403 }

static int iscsi_tx_data_out ( struct iscsi_session iscsi  )  [static]

Send iSCSI data-out data segment.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code

Definition at line 411 of file iscsi.c.

References assert, iscsi_session::command, copy_from_user(), scsi_command::data_out, iscsi_bhs::data_out, scsi_command::data_out_len, ENOMEM, iob_put, ISCSI_DATA_LEN, iscsi_bhs_data_out::lengths, ntohl, NULL, iscsi_bhs_data_out::offset, offset, iscsi_session::socket, iscsi_session::tx_bhs, xfer_alloc_iob(), and xfer_deliver_iob().

Referenced by iscsi_tx_data().

00411                                                              {
00412         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
00413         struct io_buffer *iobuf;
00414         unsigned long offset;
00415         size_t len;
00416 
00417         offset = ntohl ( data_out->offset );
00418         len = ISCSI_DATA_LEN ( data_out->lengths );
00419 
00420         assert ( iscsi->command != NULL );
00421         assert ( iscsi->command->data_out );
00422         assert ( ( offset + len ) <= iscsi->command->data_out_len );
00423 
00424         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
00425         if ( ! iobuf )
00426                 return -ENOMEM;
00427         
00428         copy_from_user ( iob_put ( iobuf, len ),
00429                          iscsi->command->data_out, offset, len );
00430 
00431         return xfer_deliver_iob ( &iscsi->socket, iobuf );
00432 }

static int iscsi_build_login_request_strings ( struct iscsi_session iscsi,
void *  data,
size_t  len 
) [static]

Build iSCSI login request strings.

Parameters:
iscsi iSCSI session
These are the initial set of strings sent in the first login request PDU. We want the following settings:

HeaderDigest=None DataDigest=None MaxConnections is irrelevant; we make only one connection anyway [4] InitialR2T=Yes [1] ImmediateData is irrelevant; we never send immediate data [4] MaxRecvDataSegmentLength=8192 (default; we don't care) [3] MaxBurstLength=262144 (default; we don't care) [3] FirstBurstLength=262144 (default; we don't care) DefaultTime2Wait=0 [2] DefaultTime2Retain=0 [2] MaxOutstandingR2T=1 DataPDUInOrder=Yes DataSequenceInOrder=Yes ErrorRecoveryLevel=0

[1] InitialR2T has an OR resolution function, so the target may force us to use it. We therefore simplify our logic by always using it.

[2] These ensure that we can safely start a new task once we have reconnected after a failure, without having to manually tidy up after the old one.

[3] We are quite happy to use the RFC-defined default values for these parameters, but some targets (notably OpenSolaris) incorrectly assume a default value of zero, so we explicitly specify the default values.

[4] We are quite happy to use the RFC-defined default values for these parameters, but some targets (notably a QNAP TS-639Pro) fail unless they are supplied, so we explicitly specify the default values.

Definition at line 481 of file iscsi.c.

References assert, iscsi_session::chap, iscsi_session::chap_challenge, iscsi_session::initiator_username, iscsi_initiator_iqn(), ISCSI_STATUS_STRINGS_CHAP_ALGORITHM, ISCSI_STATUS_STRINGS_CHAP_CHALLENGE, ISCSI_STATUS_STRINGS_CHAP_RESPONSE, ISCSI_STATUS_STRINGS_OPERATIONAL, ISCSI_STATUS_STRINGS_SECURITY, NULL, chap_response::response, chap_response::response_len, ssnprintf(), iscsi_session::status, iscsi_session::target_iqn, and iscsi_session::target_username.

Referenced by iscsi_start_login(), and iscsi_tx_login_request().

00482                                                                         {
00483         unsigned int used = 0;
00484         unsigned int i;
00485         const char *auth_method;
00486 
00487         if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
00488                 /* Default to allowing no authentication */
00489                 auth_method = "None";
00490                 /* If we have a credential to supply, permit CHAP */
00491                 if ( iscsi->initiator_username )
00492                         auth_method = "CHAP,None";
00493                 /* If we have a credential to check, force CHAP */
00494                 if ( iscsi->target_username )
00495                         auth_method = "CHAP";
00496                 used += ssnprintf ( data + used, len - used,
00497                                     "InitiatorName=%s%c"
00498                                     "TargetName=%s%c"
00499                                     "SessionType=Normal%c"
00500                                     "AuthMethod=%s%c",
00501                                     iscsi_initiator_iqn(), 0,
00502                                     iscsi->target_iqn, 0, 0,
00503                                     auth_method, 0 );
00504         }
00505 
00506         if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
00507                 used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
00508         }
00509         
00510         if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
00511                 assert ( iscsi->initiator_username != NULL );
00512                 used += ssnprintf ( data + used, len - used,
00513                                     "CHAP_N=%s%cCHAP_R=0x",
00514                                     iscsi->initiator_username, 0 );
00515                 for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
00516                         used += ssnprintf ( data + used, len - used, "%02x",
00517                                             iscsi->chap.response[i] );
00518                 }
00519                 used += ssnprintf ( data + used, len - used, "%c", 0 );
00520         }
00521 
00522         if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
00523                 used += ssnprintf ( data + used, len - used,
00524                                     "CHAP_I=%d%cCHAP_C=0x",
00525                                     iscsi->chap_challenge[0], 0 );
00526                 for ( i = 1 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
00527                         used += ssnprintf ( data + used, len - used, "%02x",
00528                                             iscsi->chap_challenge[i] );
00529                 }
00530                 used += ssnprintf ( data + used, len - used, "%c", 0 );
00531         }
00532 
00533         if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
00534                 used += ssnprintf ( data + used, len - used,
00535                                     "HeaderDigest=None%c"
00536                                     "DataDigest=None%c"
00537                                     "MaxConnections=1%c"
00538                                     "InitialR2T=Yes%c"
00539                                     "ImmediateData=No%c"
00540                                     "MaxRecvDataSegmentLength=8192%c"
00541                                     "MaxBurstLength=262144%c"
00542                                     "DefaultTime2Wait=0%c"
00543                                     "DefaultTime2Retain=0%c"
00544                                     "MaxOutstandingR2T=1%c"
00545                                     "DataPDUInOrder=Yes%c"
00546                                     "DataSequenceInOrder=Yes%c"
00547                                     "ErrorRecoveryLevel=0%c",
00548                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
00549         }
00550 
00551         return used;
00552 }

static void iscsi_login_request_done ( struct iscsi_session iscsi  )  [static]

Complete iSCSI login request PDU transmission.

Parameters:
iscsi iSCSI session

Definition at line 588 of file iscsi.c.

References iscsi_session::chap, chap_finish(), ISCSI_STATUS_STRINGS_MASK, and iscsi_session::status.

Referenced by iscsi_tx_done().

00588                                                                      {
00589 
00590         /* Clear any "strings to send" flags */
00591         iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
00592 
00593         /* Free any dynamically allocated storage used for login */
00594         chap_finish ( &iscsi->chap );
00595 }

static int iscsi_tx_login_request ( struct iscsi_session iscsi  )  [static]

Transmit data segment of an iSCSI login request PDU.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code
For login requests, the data segment consists of the login strings.

Definition at line 605 of file iscsi.c.

References io_buffer::data, ENOMEM, iob_put, iscsi_build_login_request_strings(), ISCSI_DATA_LEN, iscsi_bhs_login_request::lengths, iscsi_bhs::login_request, iscsi_session::socket, iscsi_session::tx_bhs, xfer_alloc_iob(), and xfer_deliver_iob().

Referenced by iscsi_tx_data().

00605                                                                   {
00606         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
00607         struct io_buffer *iobuf;
00608         size_t len;
00609 
00610         len = ISCSI_DATA_LEN ( request->lengths );
00611         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
00612         if ( ! iobuf )
00613                 return -ENOMEM;
00614         iob_put ( iobuf, len );
00615         iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
00616         return xfer_deliver_iob ( &iscsi->socket, iobuf );
00617 }

static int iscsi_handle_targetaddress_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI TargetAddress text value.

Parameters:
iscsi iSCSI session
value TargetAddress value
Return values:
rc Return status code

Definition at line 626 of file iscsi.c.

References DBGC, ENOMEM, free(), htons, ISCSI_PORT, NULL, strchr(), strdup(), strtoul(), iscsi_session::target_address, and iscsi_session::target_port.

00627                                                                   {
00628         char *separator;
00629 
00630         DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
00631 
00632         /* Replace target address */
00633         free ( iscsi->target_address );
00634         iscsi->target_address = strdup ( value );
00635         if ( ! iscsi->target_address )
00636                 return -ENOMEM;
00637 
00638         /* Replace target port */
00639         iscsi->target_port = htons ( ISCSI_PORT );
00640         separator = strchr ( iscsi->target_address, ':' );
00641         if ( separator ) {
00642                 *separator = '\0';
00643                 iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
00644         }
00645 
00646         return 0;
00647 }

static int iscsi_handle_authmethod_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI AuthMethod text value.

Parameters:
iscsi iSCSI session
value AuthMethod value
Return values:
rc Return status code

Definition at line 656 of file iscsi.c.

References DBGC, ISCSI_STATUS_AUTH_FORWARD_REQUIRED, ISCSI_STATUS_STRINGS_CHAP_ALGORITHM, iscsi_session::status, and strcmp().

00657                                                                {
00658 
00659         /* If server requests CHAP, send the CHAP_A string */
00660         if ( strcmp ( value, "CHAP" ) == 0 ) {
00661                 DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
00662                        iscsi );
00663                 iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
00664                                    ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
00665         }
00666 
00667         return 0;
00668 }

static int iscsi_handle_chap_a_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI CHAP_A text value.

Parameters:
iscsi iSCSI session
value CHAP_A value
Return values:
rc Return status code

Definition at line 677 of file iscsi.c.

References DBGC, EPROTO_INVALID_CHAP_ALGORITHM, and strcmp().

00678                                                            {
00679 
00680         /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
00681          * the server responds with anything else it is a protocol
00682          * violation.
00683          */
00684         if ( strcmp ( value, "5" ) != 0 ) {
00685                 DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
00686                        iscsi, value );
00687                 return -EPROTO_INVALID_CHAP_ALGORITHM;
00688         }
00689 
00690         return 0;
00691 }

static int iscsi_handle_chap_i_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI CHAP_I text value.

Parameters:
iscsi iSCSI session
value CHAP_I value
Return values:
rc Return status code

Definition at line 700 of file iscsi.c.

References iscsi_session::chap, chap_finish(), chap_init(), chap_set_identifier(), chap_update(), DBGC, EPROTO_INVALID_CHAP_IDENTIFIER, iscsi_session::initiator_password, md5_algorithm, strerror(), strlen(), and strtoul().

00701                                                            {
00702         unsigned int identifier;
00703         char *endp;
00704         int rc;
00705 
00706         /* The CHAP identifier is an integer value */
00707         identifier = strtoul ( value, &endp, 0 );
00708         if ( *endp != '\0' ) {
00709                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
00710                        iscsi, value );
00711                 return -EPROTO_INVALID_CHAP_IDENTIFIER;
00712         }
00713 
00714         /* Prepare for CHAP with MD5 */
00715         chap_finish ( &iscsi->chap );
00716         if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
00717                 DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
00718                        iscsi, strerror ( rc ) );
00719                 return rc;
00720         }
00721 
00722         /* Identifier and secret are the first two components of the
00723          * challenge.
00724          */
00725         chap_set_identifier ( &iscsi->chap, identifier );
00726         if ( iscsi->initiator_password ) {
00727                 chap_update ( &iscsi->chap, iscsi->initiator_password,
00728                               strlen ( iscsi->initiator_password ) );
00729         }
00730 
00731         return 0;
00732 }

static int iscsi_handle_chap_c_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI CHAP_C text value.

Parameters:
iscsi iSCSI session
value CHAP_C value
Return values:
rc Return status code

Definition at line 741 of file iscsi.c.

References iscsi_session::chap, iscsi_session::chap_challenge, chap_respond(), chap_update(), DBGC, EPROTO_INVALID_CHAP_CHALLENGE, ISCSI_STATUS_STRINGS_CHAP_CHALLENGE, ISCSI_STATUS_STRINGS_CHAP_RESPONSE, memcpy, random(), iscsi_session::status, strtoul(), and iscsi_session::target_username.

00742                                                            {
00743         char buf[3];
00744         char *endp;
00745         uint8_t byte;
00746         unsigned int i;
00747 
00748         /* Check and strip leading "0x" */
00749         if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
00750                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
00751                        iscsi, value );
00752                 return -EPROTO_INVALID_CHAP_CHALLENGE;
00753         }
00754         value += 2;
00755 
00756         /* Process challenge an octet at a time */
00757         for ( ; ( value[0] && value[1] ) ; value += 2 ) {
00758                 memcpy ( buf, value, 2 );
00759                 buf[2] = 0;
00760                 byte = strtoul ( buf, &endp, 16 );
00761                 if ( *endp != '\0' ) {
00762                         DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
00763                                "byte \"%s\"\n", iscsi, buf );
00764                         return -EPROTO_INVALID_CHAP_CHALLENGE;
00765                 }
00766                 chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
00767         }
00768 
00769         /* Build CHAP response */
00770         DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
00771         chap_respond ( &iscsi->chap );
00772         iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
00773 
00774         /* Send CHAP challenge, if applicable */
00775         if ( iscsi->target_username ) {
00776                 iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
00777                 /* Generate CHAP challenge data */
00778                 for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
00779                         iscsi->chap_challenge[i] = random();
00780                 }
00781         }
00782 
00783         return 0;
00784 }

static int iscsi_handle_chap_n_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI CHAP_N text value.

Parameters:
iscsi iSCSI session
value CHAP_N value
Return values:
rc Return status code

Definition at line 793 of file iscsi.c.

References DBGC, EACCES_INCORRECT_TARGET_USERNAME, strcmp(), and iscsi_session::target_username.

00794                                                            {
00795 
00796         /* The target username isn't actually involved at any point in
00797          * the authentication process; it merely serves to identify
00798          * which password the target is using to generate the CHAP
00799          * response.  We unnecessarily verify that the username is as
00800          * expected, in order to provide mildly helpful diagnostics if
00801          * the target is supplying the wrong username/password
00802          * combination.
00803          */
00804         if ( iscsi->target_username &&
00805              ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
00806                 DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
00807                        "(wanted \"%s\")\n",
00808                        iscsi, value, iscsi->target_username );
00809                 return -EACCES_INCORRECT_TARGET_USERNAME;
00810         }
00811 
00812         return 0;
00813 }

static int iscsi_handle_chap_r_value ( struct iscsi_session iscsi,
const char *  value 
) [static]

Handle iSCSI CHAP_R text value.

Parameters:
iscsi iSCSI session
value CHAP_R value
Return values:
rc Return status code

Definition at line 822 of file iscsi.c.

References assert, iscsi_session::chap, iscsi_session::chap_challenge, chap_finish(), chap_init(), chap_respond(), chap_set_identifier(), chap_update(), DBGC, EACCES_INCORRECT_TARGET_PASSWORD, EPROTO_INVALID_CHAP_RESPONSE, ISCSI_STATUS_AUTH_REVERSE_OK, md5_algorithm, memcpy, chap_response::response, chap_response::response_len, iscsi_session::status, strerror(), strlen(), strtoul(), and iscsi_session::target_password.

00823                                                            {
00824         char buf[3];
00825         char *endp;
00826         uint8_t byte;
00827         unsigned int i;
00828         int rc;
00829 
00830         /* Generate CHAP response for verification */
00831         chap_finish ( &iscsi->chap );
00832         if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
00833                 DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
00834                        iscsi, strerror ( rc ) );
00835                 return rc;
00836         }
00837         chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
00838         if ( iscsi->target_password ) {
00839                 chap_update ( &iscsi->chap, iscsi->target_password,
00840                               strlen ( iscsi->target_password ) );
00841         }
00842         chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
00843                       ( sizeof ( iscsi->chap_challenge ) - 1 ) );
00844         chap_respond ( &iscsi->chap );
00845 
00846         /* Check and strip leading "0x" */
00847         if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
00848                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
00849                        iscsi, value );
00850                 return -EPROTO_INVALID_CHAP_RESPONSE;
00851         }
00852         value += 2;
00853 
00854         /* Check CHAP response length */
00855         if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
00856                 DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
00857                        iscsi );
00858                 return -EPROTO_INVALID_CHAP_RESPONSE;
00859         }
00860 
00861         /* Process response an octet at a time */
00862         for ( i = 0 ; ( value[0] && value[1] ) ; value += 2, i++ ) {
00863                 memcpy ( buf, value, 2 );
00864                 buf[2] = 0;
00865                 byte = strtoul ( buf, &endp, 16 );
00866                 if ( *endp != '\0' ) {
00867                         DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
00868                                "byte \"%s\"\n", iscsi, buf );
00869                         return -EPROTO_INVALID_CHAP_RESPONSE;
00870                 }
00871                 if ( byte != iscsi->chap.response[i] ) {
00872                         DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
00873                                "response\n", iscsi );
00874                         return -EACCES_INCORRECT_TARGET_PASSWORD;
00875                 }
00876         }
00877         assert ( i == iscsi->chap.response_len );
00878 
00879         /* Mark session as authenticated */
00880         iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
00881 
00882         return 0;
00883 }

static int iscsi_handle_string ( struct iscsi_session iscsi,
const char *  string 
) [static]

Handle iSCSI string.

Parameters:
iscsi iSCSI session
string iSCSI string (in "key=value" format)
Return values:
rc Return status code

Definition at line 921 of file iscsi.c.

References DBGC, iscsi_string_type::handle, iscsi_string_type::key, strerror(), strlen(), and strncmp().

Referenced by iscsi_handle_strings().

00922                                                       {
00923         struct iscsi_string_type *type;
00924         size_t key_len;
00925         int rc;
00926 
00927         for ( type = iscsi_string_types ; type->key ; type++ ) {
00928                 key_len = strlen ( type->key );
00929                 if ( strncmp ( string, type->key, key_len ) != 0 )
00930                         continue;
00931                 DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
00932                 if ( ( rc = type->handle ( iscsi,
00933                                            ( string + key_len ) ) ) != 0 ) {
00934                         DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
00935                                iscsi, string, strerror ( rc ) );
00936                         return rc;
00937                 }
00938                 return 0;
00939         }
00940         DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
00941         return 0;
00942 }

static int iscsi_handle_strings ( struct iscsi_session iscsi,
const char *  strings,
size_t  len 
) [static]

Handle iSCSI strings.

Parameters:
iscsi iSCSI session
string iSCSI string buffer
len Length of string buffer
Return values:
rc Return status code

Definition at line 952 of file iscsi.c.

References iscsi_handle_string(), and strnlen().

Referenced by iscsi_rx_login_response().

00953                                                                     {
00954         size_t string_len;
00955         int rc;
00956 
00957         /* Handle each string in turn, taking care not to overrun the
00958          * data buffer in case of badly-terminated data.
00959          */
00960         while ( 1 ) {
00961                 string_len = ( strnlen ( strings, len ) + 1 );
00962                 if ( string_len > len )
00963                         break;
00964                 if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
00965                         return rc;
00966                 strings += string_len;
00967                 len -= string_len;
00968         }
00969         return 0;
00970 }

static int iscsi_rx_buffered_data ( struct iscsi_session iscsi,
const void *  data,
size_t  len 
) [static]

Receive PDU data into buffer.

Parameters:
iscsi iSCSI session
data Data to receive
len Length of data
Return values:
rc Return status code
This can be used when the RX PDU type handler wishes to buffer up all received data and process the PDU as a single unit. The caller is repsonsible for calling iscsi_rx_buffered_data_done() after processing the data.

Definition at line 985 of file iscsi.c.

References assert, ENOMEM, malloc(), memcpy, iscsi_session::rx_buffer, iscsi_session::rx_len, and iscsi_session::rx_offset.

Referenced by iscsi_rx_login_response().

00986                                                                    {
00987 
00988         /* Allocate buffer on first call */
00989         if ( ! iscsi->rx_buffer ) {
00990                 iscsi->rx_buffer = malloc ( iscsi->rx_len );
00991                 if ( ! iscsi->rx_buffer )
00992                         return -ENOMEM;
00993         }
00994 
00995         /* Copy data to buffer */
00996         assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
00997         memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
00998 
00999         return 0;
01000 }

static int iscsi_status_to_rc ( unsigned int  status_class,
unsigned int  status_detail 
) [static]

Convert iSCSI response status to return status code.

Parameters:
status_class iSCSI status class
status_detail iSCSI status detail
Return values:
rc Return status code

Definition at line 1009 of file iscsi.c.

References EINVAL, EIO, ENODEV, ENOTSUP_INITIATOR_STATUS, EPERM_INITIATOR_AUTHENTICATION, EPERM_INITIATOR_AUTHORISATION, ISCSI_STATUS_INITIATOR_ERROR, ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION, ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION, ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND, ISCSI_STATUS_INITIATOR_ERROR_REMOVED, and ISCSI_STATUS_TARGET_ERROR.

Referenced by iscsi_rx_login_response().

01010                                                              {
01011         switch ( status_class ) {
01012         case ISCSI_STATUS_INITIATOR_ERROR :
01013                 switch ( status_detail ) {
01014                 case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
01015                         return -EPERM_INITIATOR_AUTHENTICATION;
01016                 case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
01017                         return -EPERM_INITIATOR_AUTHORISATION;
01018                 case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
01019                 case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
01020                         return -ENODEV;
01021                 default :
01022                         return -ENOTSUP_INITIATOR_STATUS;
01023                 }
01024         case ISCSI_STATUS_TARGET_ERROR :
01025                 return -EIO;
01026         default :
01027                 return -EINVAL;
01028         }
01029 }

static int iscsi_rx_login_response ( struct iscsi_session iscsi,
const void *  data,
size_t  len,
size_t  remaining 
) [static]

Receive data segment of an iSCSI login response PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code

Definition at line 1040 of file iscsi.c.

References DBGC, EIO, EPROTO, iscsi_bhs_login_response::flags, iscsi_session::instant_rc, iscsi_close_connection(), iscsi_handle_strings(), ISCSI_LOGIN_FLAG_TRANSITION, ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE, ISCSI_LOGIN_NSG_MASK, ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION, iscsi_open_connection(), iscsi_rx_buffered_data(), iscsi_rx_buffered_data_done(), iscsi_start_command(), iscsi_start_login(), ISCSI_STATUS_AUTH_REVERSE_OK, ISCSI_STATUS_AUTH_REVERSE_REQUIRED, ISCSI_STATUS_FULL_FEATURE_PHASE, ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE, ISCSI_STATUS_PHASE_MASK, ISCSI_STATUS_REDIRECT, ISCSI_STATUS_STRINGS_MASK, ISCSI_STATUS_STRINGS_OPERATIONAL, iscsi_status_to_rc(), iscsi_bhs::login_response, ntohl, iscsi_session::retry_count, iscsi_session::rx_bhs, iscsi_session::rx_buffer, iscsi_session::rx_len, iscsi_session::status, iscsi_bhs_login_response::status_class, iscsi_bhs_login_response::status_detail, strerror(), iscsi_bhs_login_response::tsih, and iscsi_session::tsih.

Referenced by iscsi_rx_data().

01042                                                         {
01043         struct iscsi_bhs_login_response *response
01044                 = &iscsi->rx_bhs.login_response;
01045         int rc;
01046 
01047         /* Buffer up the PDU data */
01048         if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
01049                 DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
01050                        iscsi, strerror ( rc ) );
01051                 return rc;
01052         }
01053         if ( remaining )
01054                 return 0;
01055 
01056         /* Process string data and discard string buffer */
01057         if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
01058                                            iscsi->rx_len ) ) != 0 )
01059                 return rc;
01060         iscsi_rx_buffered_data_done ( iscsi );
01061 
01062         /* Check for login redirection */
01063         if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
01064                 DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
01065                 iscsi_close_connection ( iscsi, 0 );
01066                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
01067                         DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
01068                                iscsi, strerror ( rc ) );
01069                         return rc;
01070                 }
01071                 return 0;
01072         }
01073 
01074         /* Check for fatal errors */
01075         if ( response->status_class != 0 ) {
01076                 DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
01077                        response->status_class, response->status_detail );
01078                 rc = iscsi_status_to_rc ( response->status_class,
01079                                           response->status_detail );
01080                 iscsi->instant_rc = rc;
01081                 return rc;
01082         }
01083 
01084         /* Handle login transitions */
01085         if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
01086                 iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
01087                                     ISCSI_STATUS_STRINGS_MASK );
01088                 switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
01089                 case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
01090                         iscsi->status |=
01091                                 ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
01092                                   ISCSI_STATUS_STRINGS_OPERATIONAL );
01093                         break;
01094                 case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
01095                         iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
01096                         break;
01097                 default:
01098                         DBGC ( iscsi, "iSCSI %p got invalid response flags "
01099                                "%02x\n", iscsi, response->flags );
01100                         return -EIO;
01101                 }
01102         }
01103 
01104         /* Send next login request PDU if we haven't reached the full
01105          * feature phase yet.
01106          */
01107         if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
01108              ISCSI_STATUS_FULL_FEATURE_PHASE ) {
01109                 iscsi_start_login ( iscsi );
01110                 return 0;
01111         }
01112 
01113         /* Check that target authentication was successful (if required) */
01114         if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
01115              ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
01116                 DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
01117                        "authentication\n", iscsi );
01118                 return -EPROTO;
01119         }
01120 
01121         /* Reset retry count */
01122         iscsi->retry_count = 0;
01123 
01124         /* Record TSIH for future reference */
01125         iscsi->tsih = ntohl ( response->tsih );
01126         
01127         /* Send the actual SCSI command */
01128         iscsi_start_command ( iscsi );
01129 
01130         return 0;
01131 }

static int iscsi_tx_nothing ( struct iscsi_session *iscsi  __unused  )  [static]

Transmit nothing.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code

Definition at line 1163 of file iscsi.c.

Referenced by iscsi_tx_step().

01163                                                                      {
01164         return 0;
01165 }

static int iscsi_tx_bhs ( struct iscsi_session iscsi  )  [static]

Transmit basic header segment of an iSCSI PDU.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code

Definition at line 1173 of file iscsi.c.

References iscsi_session::socket, iscsi_session::tx_bhs, and xfer_deliver_raw().

Referenced by iscsi_tx_step().

01173                                                         {
01174         return xfer_deliver_raw ( &iscsi->socket,  &iscsi->tx_bhs,
01175                                   sizeof ( iscsi->tx_bhs ) );
01176 }

static int iscsi_tx_data ( struct iscsi_session iscsi  )  [static]

Transmit data segment of an iSCSI PDU.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code
Handle transmission of part of a PDU data segment. iscsi::tx_bhs will be valid when this is called.

Definition at line 1187 of file iscsi.c.

References iscsi_bhs::common, ISCSI_OPCODE_DATA_OUT, ISCSI_OPCODE_LOGIN_REQUEST, ISCSI_OPCODE_MASK, iscsi_tx_data_out(), iscsi_tx_login_request(), iscsi_bhs_common::opcode, and iscsi_session::tx_bhs.

Referenced by iscsi_tx_step().

01187                                                          {
01188         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
01189 
01190         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
01191         case ISCSI_OPCODE_DATA_OUT:
01192                 return iscsi_tx_data_out ( iscsi );
01193         case ISCSI_OPCODE_LOGIN_REQUEST:
01194                 return iscsi_tx_login_request ( iscsi );
01195         default:
01196                 /* Nothing to send in other states */
01197                 return 0;
01198         }
01199 }

static int iscsi_tx_data_padding ( struct iscsi_session iscsi  )  [static]

Transmit data padding of an iSCSI PDU.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code
Handle transmission of any data padding in a PDU data segment. iscsi::tx_bhs will be valid when this is called.

Definition at line 1210 of file iscsi.c.

References iscsi_bhs::common, ISCSI_DATA_PAD_LEN, iscsi_bhs_common::lengths, iscsi_session::socket, iscsi_session::tx_bhs, and xfer_deliver_raw().

Referenced by iscsi_tx_step().

01210                                                                  {
01211         static const char pad[] = { '\0', '\0', '\0' };
01212         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
01213         size_t pad_len;
01214         
01215         pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
01216         if ( ! pad_len )
01217                 return 0;
01218 
01219         return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
01220 }

static void iscsi_tx_done ( struct iscsi_session iscsi  )  [static]

Complete iSCSI PDU transmission.

Parameters:
iscsi iSCSI session
Called when a PDU has been completely transmitted and the TX state machine is about to enter the idle state. iscsi::tx_bhs will be valid for the just-completed PDU when this is called.

Definition at line 1231 of file iscsi.c.

References iscsi_bhs::common, iscsi_data_out_done(), iscsi_login_request_done(), ISCSI_OPCODE_DATA_OUT, ISCSI_OPCODE_LOGIN_REQUEST, ISCSI_OPCODE_MASK, iscsi_bhs_common::opcode, and iscsi_session::tx_bhs.

Referenced by iscsi_tx_step().

01231                                                           {
01232         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
01233 
01234         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
01235         case ISCSI_OPCODE_DATA_OUT:
01236                 iscsi_data_out_done ( iscsi );
01237         case ISCSI_OPCODE_LOGIN_REQUEST:
01238                 iscsi_login_request_done ( iscsi );
01239         default:
01240                 /* No action */
01241                 break;
01242         }
01243 }

static void iscsi_tx_step ( struct process process  )  [static]

Transmit iSCSI PDU.

Parameters:
iscsi iSCSI session
buf Temporary data buffer
len Length of temporary data buffer
Constructs data to be sent for the current TX state

Definition at line 1254 of file iscsi.c.

References assert, iscsi_bhs::common, container_of, DBGC, ISCSI_DATA_LEN, ISCSI_DATA_PAD_LEN, ISCSI_TX_AHS, iscsi_tx_bhs(), ISCSI_TX_BHS, iscsi_tx_data(), ISCSI_TX_DATA, iscsi_tx_data_padding(), ISCSI_TX_DATA_PADDING, iscsi_tx_done(), ISCSI_TX_IDLE, iscsi_tx_nothing(), iscsi_bhs_common::lengths, iscsi_session::socket, strerror(), iscsi_session::tx_bhs, iscsi_session::tx_state, and xfer_window().

Referenced by iscsi_attach().

01254                                                       {
01255         struct iscsi_session *iscsi =
01256                 container_of ( process, struct iscsi_session, process );
01257         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
01258         int ( * tx ) ( struct iscsi_session *iscsi );
01259         enum iscsi_tx_state next_state;
01260         size_t tx_len;
01261         int rc;
01262 
01263         /* Select fragment to transmit */
01264         while ( 1 ) {
01265                 switch ( iscsi->tx_state ) {
01266                 case ISCSI_TX_IDLE:
01267                         /* Stop processing */
01268                         return;
01269                 case ISCSI_TX_BHS:
01270                         tx = iscsi_tx_bhs;
01271                         tx_len = sizeof ( iscsi->tx_bhs );
01272                         next_state = ISCSI_TX_AHS;
01273                         break;
01274                 case ISCSI_TX_AHS:
01275                         tx = iscsi_tx_nothing;
01276                         tx_len = 0;
01277                         next_state = ISCSI_TX_DATA;
01278                         break;
01279                 case ISCSI_TX_DATA:
01280                         tx = iscsi_tx_data;
01281                         tx_len = ISCSI_DATA_LEN ( common->lengths );
01282                         next_state = ISCSI_TX_DATA_PADDING;
01283                         break;
01284                 case ISCSI_TX_DATA_PADDING:
01285                         tx = iscsi_tx_data_padding;
01286                         tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
01287                         next_state = ISCSI_TX_IDLE;
01288                         break;
01289                 default:
01290                         assert ( 0 );
01291                         return;
01292                 }
01293 
01294                 /* Check for window availability, if needed */
01295                 if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
01296                         /* Cannot transmit at this point; stop processing */
01297                         return;
01298                 }
01299 
01300                 /* Transmit data */
01301                 if ( ( rc = tx ( iscsi ) ) != 0 ) {
01302                         DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
01303                                iscsi, strerror ( rc ) );
01304                         return;
01305                 }
01306 
01307                 /* Move to next state */
01308                 iscsi->tx_state = next_state;
01309                 if ( next_state == ISCSI_TX_IDLE )
01310                         iscsi_tx_done ( iscsi );
01311         }
01312 }

static int iscsi_rx_bhs ( struct iscsi_session iscsi,
const void *  data,
size_t  len,
size_t remaining  __unused 
) [static]

Receive basic header segment of an iSCSI PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code
This fills in iscsi::rx_bhs with the data from the BHS portion of the received PDU.

Definition at line 1326 of file iscsi.c.

References iscsi_bhs::bytes, iscsi_bhs::common, DBGC2, ISCSI_DATA_LEN, iscsi_bhs_common::lengths, memcpy, iscsi_bhs_common::opcode, iscsi_session::rx_bhs, and iscsi_session::rx_offset.

Referenced by iscsi_socket_deliver_raw().

01327                                                                   {
01328         memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
01329         if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
01330                 DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
01331                         iscsi, iscsi->rx_bhs.common.opcode,
01332                         ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
01333         }
01334         return 0;
01335 }

static int iscsi_rx_discard ( struct iscsi_session *iscsi  __unused,
const void *data  __unused,
size_t len  __unused,
size_t remaining  __unused 
) [static]

Discard portion of an iSCSI PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code
This discards data from a portion of a received PDU.

Definition at line 1348 of file iscsi.c.

Referenced by iscsi_socket_deliver_raw().

01350                                                           {
01351         /* Do nothing */
01352         return 0;
01353 }

static int iscsi_rx_data ( struct iscsi_session iscsi,
const void *  data,
size_t  len,
size_t  remaining 
) [static]

Receive data segment of an iSCSI PDU.

Parameters:
iscsi iSCSI session
data Received data
len Length of received data
remaining Data remaining after this data
Return values:
rc Return status code
Handle processing of part of a PDU data segment. iscsi::rx_bhs will be valid when this is called.

Definition at line 1367 of file iscsi.c.

References iscsi_session::cmdsn, iscsi_bhs::common_response, DBGC, ENOTSUP_OPCODE, iscsi_bhs_common_response::expcmdsn, ISCSI_OPCODE_DATA_IN, ISCSI_OPCODE_LOGIN_RESPONSE, ISCSI_OPCODE_MASK, ISCSI_OPCODE_R2T, ISCSI_OPCODE_SCSI_RESPONSE, iscsi_rx_data_in(), iscsi_rx_login_response(), iscsi_rx_r2t(), iscsi_rx_scsi_response(), ntohl, iscsi_bhs_common_response::opcode, iscsi_session::rx_bhs, iscsi_bhs_common_response::statsn, and iscsi_session::statsn.

Referenced by iscsi_socket_deliver_raw().

01368                                                           {
01369         struct iscsi_bhs_common_response *response
01370                 = &iscsi->rx_bhs.common_response;
01371 
01372         /* Update cmdsn and statsn */
01373         iscsi->cmdsn = ntohl ( response->expcmdsn );
01374         iscsi->statsn = ntohl ( response->statsn );
01375 
01376         switch ( response->opcode & ISCSI_OPCODE_MASK ) {
01377         case ISCSI_OPCODE_LOGIN_RESPONSE:
01378                 return iscsi_rx_login_response ( iscsi, data, len, remaining );
01379         case ISCSI_OPCODE_SCSI_RESPONSE:
01380                 return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
01381         case ISCSI_OPCODE_DATA_IN:
01382                 return iscsi_rx_data_in ( iscsi, data, len, remaining );
01383         case ISCSI_OPCODE_R2T:
01384                 return iscsi_rx_r2t ( iscsi, data, len, remaining );
01385         default:
01386                 if ( remaining )
01387                         return 0;
01388                 DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
01389                        response->opcode );
01390                 return -ENOTSUP_OPCODE;
01391         }
01392 }

static int iscsi_socket_deliver_raw ( struct xfer_interface socket,
const void *  data,
size_t  len 
) [static]

Receive new data.

Parameters:
socket Transport layer interface
data Received data
len Length of received data
Return values:
rc Return status code
This handles received PDUs. The receive strategy is to fill in iscsi::rx_bhs with the contents of the BHS portion of the PDU, throw away any AHS portion, and then process each part of the data portion as it arrives. The data processing routine therefore always has a full copy of the BHS available, even for portions of the data in different packets to the BHS.

Definition at line 1409 of file iscsi.c.

References assert, iscsi_bhs::common, container_of, DBGC, EINVAL, ISCSI_AHS_LEN, iscsi_close_connection(), ISCSI_DATA_LEN, ISCSI_DATA_PAD_LEN, ISCSI_RX_AHS, iscsi_rx_bhs(), ISCSI_RX_BHS, iscsi_rx_data(), ISCSI_RX_DATA, ISCSI_RX_DATA_PADDING, iscsi_rx_discard(), iscsi_scsi_done(), iscsi_bhs_common::lengths, iscsi_session::rx_bhs, iscsi_session::rx_len, iscsi_session::rx_offset, iscsi_session::rx_state, and strerror().

01410                                                                      {
01411         struct iscsi_session *iscsi =
01412                 container_of ( socket, struct iscsi_session, socket );
01413         struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
01414         int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
01415                        size_t len, size_t remaining );
01416         enum iscsi_rx_state next_state;
01417         size_t frag_len;
01418         size_t remaining;
01419         int rc;
01420 
01421         while ( 1 ) {
01422                 switch ( iscsi->rx_state ) {
01423                 case ISCSI_RX_BHS:
01424                         rx = iscsi_rx_bhs;
01425                         iscsi->rx_len = sizeof ( iscsi->rx_bhs );
01426                         next_state = ISCSI_RX_AHS;                      
01427                         break;
01428                 case ISCSI_RX_AHS:
01429                         rx = iscsi_rx_discard;
01430                         iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
01431                         next_state = ISCSI_RX_DATA;
01432                         break;
01433                 case ISCSI_RX_DATA:
01434                         rx = iscsi_rx_data;
01435                         iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
01436                         next_state = ISCSI_RX_DATA_PADDING;
01437                         break;
01438                 case ISCSI_RX_DATA_PADDING:
01439                         rx = iscsi_rx_discard;
01440                         iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
01441                         next_state = ISCSI_RX_BHS;
01442                         break;
01443                 default:
01444                         assert ( 0 );
01445                         return -EINVAL;
01446                 }
01447 
01448                 frag_len = iscsi->rx_len - iscsi->rx_offset;
01449                 if ( frag_len > len )
01450                         frag_len = len;
01451                 remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
01452                 if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
01453                         DBGC ( iscsi, "iSCSI %p could not process received "
01454                                "data: %s\n", iscsi, strerror ( rc ) );
01455                         iscsi_close_connection ( iscsi, rc );
01456                         iscsi_scsi_done ( iscsi, rc );
01457                         return rc;
01458                 }
01459 
01460                 iscsi->rx_offset += frag_len;
01461                 data += frag_len;
01462                 len -= frag_len;
01463 
01464                 /* If all the data for this state has not yet been
01465                  * received, stay in this state for now.
01466                  */
01467                 if ( iscsi->rx_offset != iscsi->rx_len )
01468                         return 0;
01469 
01470                 iscsi->rx_state = next_state;
01471                 iscsi->rx_offset = 0;
01472         }
01473 
01474         return 0;
01475 }

static void iscsi_socket_close ( struct xfer_interface socket,
int  rc 
) [static]

Handle stream connection closure.

Parameters:
socket Transport layer interface
rc Reason for close

Definition at line 1484 of file iscsi.c.

References container_of, DBGC, ECONNRESET, iscsi_session::instant_rc, iscsi_close_connection(), ISCSI_MAX_RETRIES, iscsi_open_connection(), iscsi_scsi_done(), iscsi_session::retry_count, and strerror().

01484                                                                          {
01485         struct iscsi_session *iscsi =
01486                 container_of ( socket, struct iscsi_session, socket );
01487 
01488         /* Even a graceful close counts as an error for iSCSI */
01489         if ( ! rc )
01490                 rc = -ECONNRESET;
01491 
01492         /* Close session cleanly */
01493         iscsi_close_connection ( iscsi, rc );
01494 
01495         /* Retry connection if within the retry limit, otherwise fail */
01496         if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
01497                 DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
01498                        iscsi, iscsi->retry_count );
01499                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
01500                         DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
01501                                iscsi, strerror ( rc ) );
01502                         iscsi_scsi_done ( iscsi, rc );
01503                 }
01504         } else {
01505                 DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
01506                 iscsi->instant_rc = rc;
01507                 iscsi_scsi_done ( iscsi, rc );
01508         }
01509 }

static int iscsi_vredirect ( struct xfer_interface socket,
int  type,
va_list  args 
) [static]

Handle redirection event.

Parameters:
socket Transport layer interface
type Location type
args Remaining arguments depend upon location type
Return values:
rc Return status code

Definition at line 1519 of file iscsi.c.

References container_of, LOCATION_SOCKET, memcpy, iscsi_session::target_sockaddr, va_arg, va_copy, va_end, and xfer_vreopen().

01520                                             {
01521         struct iscsi_session *iscsi =
01522                 container_of ( socket, struct iscsi_session, socket );
01523         va_list tmp;
01524         struct sockaddr *peer;
01525 
01526         /* Intercept redirects to a LOCATION_SOCKET and record the IP
01527          * address for the iBFT.  This is a bit of a hack, but avoids
01528          * inventing an ioctl()-style call to retrieve the socket
01529          * address from a data-xfer interface.
01530          */
01531         if ( type == LOCATION_SOCKET ) {
01532                 va_copy ( tmp, args );
01533                 ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
01534                 peer = va_arg ( tmp, struct sockaddr * );
01535                 memcpy ( &iscsi->target_sockaddr, peer,
01536                          sizeof ( iscsi->target_sockaddr ) );
01537                 va_end ( tmp );
01538         }
01539 
01540         return xfer_vreopen ( socket, type, args );
01541 }

static int iscsi_command ( struct scsi_device scsi,
struct scsi_command command 
) [static]

Issue SCSI command.

Parameters:
scsi SCSI device
command SCSI command
Return values:
rc Return status code

Definition at line 1568 of file iscsi.c.

References scsi_device::backend, iscsi_session::command, container_of, iscsi_session::instant_rc, iscsi_open_connection(), iscsi_start_command(), NULL, and iscsi_session::status.

Referenced by iscsi_attach().

01569                                                           {
01570         struct iscsi_session *iscsi =
01571                 container_of ( scsi->backend, struct iscsi_session, refcnt );
01572         int rc;
01573 
01574         /* Abort immediately if we have a recorded permanent failure */
01575         if ( iscsi->instant_rc )
01576                 return iscsi->instant_rc;
01577 
01578         /* Record SCSI command */
01579         iscsi->command = command;
01580 
01581         /* Issue command or open connection as appropriate */
01582         if ( iscsi->status ) {
01583                 iscsi_start_command ( iscsi );
01584         } else {
01585                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
01586                         iscsi->command = NULL;
01587                         return rc;
01588                 }
01589         }
01590 
01591         return 0;
01592 }

void iscsi_detach ( struct scsi_device scsi  ) 

Shut down iSCSI interface.

Parameters:
scsi SCSI device

Definition at line 1599 of file iscsi.c.

References scsi_device::backend, scsi_device::command, container_of, iscsi_close_connection(), NULL, iscsi_session::process, process_del(), ref_put(), scsi_detached_command(), and iscsi_session::socket.

Referenced by iscsiboot().

01599                                                {
01600         struct iscsi_session *iscsi =
01601                 container_of ( scsi->backend, struct iscsi_session, refcnt );
01602 
01603         xfer_nullify ( &iscsi->socket );
01604         iscsi_close_connection ( iscsi, 0 );
01605         process_del ( &iscsi->process );
01606         scsi->command = scsi_detached_command;
01607         ref_put ( scsi->backend );
01608         scsi->backend = NULL;
01609 }

static int iscsi_parse_root_path ( struct iscsi_session iscsi,
const char *  root_path 
) [static]

Parse iSCSI root path.

Parameters:
iscsi iSCSI session
root_path iSCSI root path (as per RFC4173)
Return values:
rc Return status code

Definition at line 1635 of file iscsi.c.

References DBGC, EINVAL, ENOMEM, ISCSI_PORT, iscsi_session::lun, NULL, NUM_RP_COMPONENTS, RP_LUN, RP_PORT, RP_SERVERNAME, RP_TARGETNAME, scsi_parse_lun(), strcpy(), strdup(), strlen(), strtoul(), iscsi_session::target_address, iscsi_session::target_iqn, and iscsi_session::target_port.

Referenced by iscsi_attach().

01636                                                            {
01637         char rp_copy[ strlen ( root_path ) + 1 ];
01638         char *rp_comp[NUM_RP_COMPONENTS];
01639         char *rp = rp_copy;
01640         int i = 0;
01641         int rc;
01642 
01643         /* Split root path into component parts */
01644         strcpy ( rp_copy, root_path );
01645         while ( 1 ) {
01646                 rp_comp[i++] = rp;
01647                 if ( i == NUM_RP_COMPONENTS )
01648                         break;
01649                 for ( ; *rp != ':' ; rp++ ) {
01650                         if ( ! *rp ) {
01651                                 DBGC ( iscsi, "iSCSI %p root path \"%s\" "
01652                                        "too short\n", iscsi, root_path );
01653                                 return -EINVAL;
01654                         }
01655                 }
01656                 *(rp++) = '\0';
01657         }
01658 
01659         /* Use root path components to configure iSCSI session */
01660         iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
01661         if ( ! iscsi->target_address )
01662                 return -ENOMEM;
01663         iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
01664         if ( ! iscsi->target_port )
01665                 iscsi->target_port = ISCSI_PORT;
01666         if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
01667                 DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
01668                        iscsi, rp_comp[RP_LUN] );
01669                 return rc;
01670         }
01671         iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
01672         if ( ! iscsi->target_iqn )
01673                 return -ENOMEM;
01674 
01675         return 0;
01676 }

static int iscsi_set_auth ( struct iscsi_session iscsi,
const char *  initiator_username,
const char *  initiator_password,
const char *  target_username,
const char *  target_password 
) [static]

Set iSCSI authentication details.

Parameters:
iscsi iSCSI session
initiator_username Initiator username, if any
initiator_password Initiator password, if any
target_username Target username, if any
target_password Target password, if any
Return values:
rc Return status code

Definition at line 1688 of file iscsi.c.

References DBGC, EINVAL, ENOMEM, iscsi_session::initiator_password, iscsi_session::initiator_username, strdup(), iscsi_session::target_password, and iscsi_session::target_username.

Referenced by iscsi_attach().

01692                                                           {
01693 
01694         /* Check for initiator or target credentials */
01695         if ( initiator_username || initiator_password ||
01696              target_username || target_password ) {
01697 
01698                 /* We must have at least an initiator username+password */
01699                 if ( ! ( initiator_username && initiator_password ) )
01700                         goto invalid_auth;
01701 
01702                 /* Store initiator credentials */
01703                 iscsi->initiator_username = strdup ( initiator_username );
01704                 if ( ! iscsi->initiator_username )
01705                         return -ENOMEM;
01706                 iscsi->initiator_password = strdup ( initiator_password );
01707                 if ( ! iscsi->initiator_password )
01708                         return -ENOMEM;
01709 
01710                 /* Check for target credentials */
01711                 if ( target_username || target_password ) {
01712 
01713                         /* We must have target username+password */
01714                         if ( ! ( target_username && target_password ) )
01715                                 goto invalid_auth;
01716 
01717                         /* Store target credentials */
01718                         iscsi->target_username = strdup ( target_username );
01719                         if ( ! iscsi->target_username )
01720                                 return -ENOMEM;
01721                         iscsi->target_password = strdup ( target_password );
01722                         if ( ! iscsi->target_password )
01723                                 return -ENOMEM;
01724                 }
01725         }
01726 
01727         return 0;
01728 
01729  invalid_auth:
01730         DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
01731                "%sname,%spw, target %sname,%spw\n", iscsi,
01732                ( initiator_username ? "" : "no " ),
01733                ( initiator_password ? "" : "no " ),
01734                ( target_username ? "" : "no " ),
01735                ( target_password ? "" : "no " ) );
01736         return -EINVAL;
01737 }

int iscsi_attach ( struct scsi_device scsi,
const char *  root_path 
)

Attach iSCSI interface.

Parameters:
scsi SCSI device
root_path iSCSI root path (as per RFC4173)
Return values:
rc Return status code

Definition at line 1746 of file iscsi.c.

References scsi_device::backend, scsi_device::command, DBGC, EINVAL, ENOMEM, ENOTSUP_DISCOVERY, refcnt::free, iscsi_command(), iscsi_free(), iscsi_initiator_password, iscsi_initiator_username, iscsi_parse_root_path(), iscsi_set_auth(), iscsi_target_password, iscsi_target_username, iscsi_tx_step(), iscsi_session::process, process_init(), ref_get(), ref_put(), iscsi_session::refcnt, iscsi_session::socket, iscsi_session::target_address, iscsi_session::target_iqn, xfer_init(), and zalloc().

Referenced by iscsiboot().

01746                                                                      {
01747         struct iscsi_session *iscsi;
01748         int rc;
01749 
01750         /* Allocate and initialise structure */
01751         iscsi = zalloc ( sizeof ( *iscsi ) );
01752         if ( ! iscsi )
01753                 return -ENOMEM;
01754         iscsi->refcnt.free = iscsi_free;
01755         xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt );
01756         process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
01757 
01758         /* Parse root path */
01759         if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
01760                 goto err;
01761         /* Set fields not specified by root path */
01762         if ( ( rc = iscsi_set_auth ( iscsi,
01763                                      iscsi_initiator_username,
01764                                      iscsi_initiator_password,
01765                                      iscsi_target_username,
01766                                      iscsi_target_password ) ) != 0 )
01767                 goto err;
01768 
01769         /* Sanity checks */
01770         if ( ! iscsi->target_address ) {
01771                 DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
01772                        iscsi );
01773                 rc = -ENOTSUP_DISCOVERY;
01774                 goto err;
01775         }
01776         if ( ! iscsi->target_iqn ) {
01777                 DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
01778                        iscsi, root_path );
01779                 rc = -EINVAL;
01780                 goto err;
01781         }
01782 
01783         /* Attach parent interface, mortalise self, and return */
01784         scsi->backend = ref_get ( &iscsi->refcnt );
01785         scsi->command = iscsi_command;
01786         ref_put ( &iscsi->refcnt );
01787         return 0;
01788         
01789  err:
01790         ref_put ( &iscsi->refcnt );
01791         return rc;
01792 }

static int apply_iscsi_string_setting ( struct iscsi_string_setting setting  )  [static]

Apply iSCSI setting.

Parameters:
setting iSCSI string setting
Return values:
rc Return status code

Definition at line 1874 of file iscsi.c.

References assert, ENOMEM, fetch_setting_len(), fetch_string_setting(), free(), malloc(), NULL, iscsi_string_setting::prefix, iscsi_string_setting::setting, strcpy(), iscsi_string_setting::string, and strlen().

Referenced by apply_iscsi_settings().

01874                                                                               {
01875         size_t prefix_len;
01876         int setting_len;
01877         size_t len;
01878         int check_len;
01879         char *p;
01880 
01881         /* Free old string */
01882         free ( *setting->string );
01883         *setting->string = NULL;
01884 
01885         /* Allocate new string */
01886         prefix_len = strlen ( setting->prefix );
01887         setting_len = fetch_setting_len ( NULL, setting->setting );
01888         if ( setting_len < 0 ) {
01889                 /* Missing settings are not errors; leave strings as NULL */
01890                 return 0;
01891         }
01892         len = ( prefix_len + setting_len + 1 );
01893         p = *setting->string = malloc ( len );
01894         if ( ! p )
01895                 return -ENOMEM;
01896 
01897         /* Fill new string */
01898         strcpy ( p, setting->prefix );
01899         check_len = fetch_string_setting ( NULL, setting->setting,
01900                                            ( p + prefix_len ),
01901                                            ( len - prefix_len ) );
01902         assert ( check_len == setting_len );
01903 
01904         return 0;
01905 }

static int apply_iscsi_settings ( void   )  [static]

Apply iSCSI settings.

Return values:
rc Return status code

Definition at line 1912 of file iscsi.c.

References apply_iscsi_string_setting(), DBG, setting::name, and iscsi_string_setting::setting.

01912                                          {
01913         struct iscsi_string_setting *setting;
01914         unsigned int i;
01915         int rc;
01916 
01917         for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
01918                             sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
01919                 setting = &iscsi_string_settings[i];
01920                 if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
01921                         DBG ( "iSCSI could not apply setting %s\n",
01922                               setting->setting->name );
01923                         return rc;
01924                 }
01925         }
01926 
01927         return 0;
01928 }

const char* iscsi_initiator_iqn ( void   ) 

Get iSCSI initiator IQN.

Parameters:
iscsi iSCSI session
Return values:
rc Return status code

Definition at line 1947 of file iscsi.c.

References iscsi_default_initiator_iqn, and iscsi_explicit_initiator_iqn.

Referenced by ibft_fill_initiator(), and iscsi_build_login_request_strings().

01947                                           {
01948 
01949         if ( iscsi_explicit_initiator_iqn )
01950                 return iscsi_explicit_initiator_iqn;
01951         if ( iscsi_default_initiator_iqn )
01952                 return iscsi_default_initiator_iqn;
01953         return "iqn.2000-09.org.etherboot:UNKNOWN";
01954 }


Variable Documentation

iSCSI initiator name (explicitly specified)

Definition at line 62 of file iscsi.c.

Referenced by iscsi_initiator_iqn().

Default iSCSI initiator name (constructed from hostname).

Definition at line 65 of file iscsi.c.

Referenced by iscsi_initiator_iqn().

char* iscsi_initiator_username [static]

iSCSI initiator username

Definition at line 68 of file iscsi.c.

Referenced by iscsi_attach().

char* iscsi_initiator_password [static]

iSCSI initiator password

Definition at line 71 of file iscsi.c.

Referenced by iscsi_attach().

char* iscsi_target_username [static]

iSCSI target username

Definition at line 74 of file iscsi.c.

Referenced by iscsi_attach().

char* iscsi_target_password [static]

iSCSI target password

Definition at line 77 of file iscsi.c.

Referenced by iscsi_attach().

Initial value:

 {
        { "TargetAddress=", iscsi_handle_targetaddress_value },
        { "AuthMethod=", iscsi_handle_authmethod_value },
        { "CHAP_A=", iscsi_handle_chap_a_value },
        { "CHAP_I=", iscsi_handle_chap_i_value },
        { "CHAP_C=", iscsi_handle_chap_c_value },
        { "CHAP_N=", iscsi_handle_chap_n_value },
        { "CHAP_R=", iscsi_handle_chap_r_value },
        { NULL, NULL }
}
iSCSI text strings that we want to handle

Definition at line 903 of file iscsi.c.

Initial value:

 {
        .close          = iscsi_socket_close,
        .vredirect      = iscsi_vredirect,
        .window         = unlimited_xfer_window,
        .alloc_iob      = default_xfer_alloc_iob,
        .deliver_iob    = xfer_deliver_as_raw,
        .deliver_raw    = iscsi_socket_deliver_raw,
}
iSCSI socket operations

Definition at line 1545 of file iscsi.c.

iSCSI string settings

Definition at line 1835 of file iscsi.c.

struct settings_applicator iscsi_settings_applicator __settings_applicator

Initial value:

 {
        .apply = apply_iscsi_settings,
}
iSCSI settings applicator

Definition at line 1931 of file iscsi.c.


Generated on Tue Apr 6 20:01:56 2010 for gPXE by  doxygen 1.5.7.1