Home | History | Annotate | Download | only in tcp
      1 /*
      2  * Copyright (C) 2006 Michael Brown <mbrown (at) fensystems.co.uk>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <stddef.h>
     22 #include <string.h>
     23 #include <stdlib.h>
     24 #include <stdio.h>
     25 #include <errno.h>
     26 #include <assert.h>
     27 #include <byteswap.h>
     28 #include <gpxe/vsprintf.h>
     29 #include <gpxe/socket.h>
     30 #include <gpxe/xfer.h>
     31 #include <gpxe/open.h>
     32 #include <gpxe/scsi.h>
     33 #include <gpxe/process.h>
     34 #include <gpxe/uaccess.h>
     35 #include <gpxe/tcpip.h>
     36 #include <gpxe/settings.h>
     37 #include <gpxe/features.h>
     38 #include <gpxe/iscsi.h>
     39 
     40 /** @file
     41  *
     42  * iSCSI protocol
     43  *
     44  */
     45 
     46 FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
     47 
     48 /** iSCSI initiator name (explicitly specified) */
     49 static char *iscsi_explicit_initiator_iqn;
     50 
     51 /** Default iSCSI initiator name (constructed from hostname) */
     52 static char *iscsi_default_initiator_iqn;
     53 
     54 /** iSCSI initiator username */
     55 static char *iscsi_initiator_username;
     56 
     57 /** iSCSI initiator password */
     58 static char *iscsi_initiator_password;
     59 
     60 /** iSCSI target username */
     61 static char *iscsi_target_username;
     62 
     63 /** iSCSI target password */
     64 static char *iscsi_target_password;
     65 
     66 static void iscsi_start_tx ( struct iscsi_session *iscsi );
     67 static void iscsi_start_login ( struct iscsi_session *iscsi );
     68 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
     69 				   unsigned int datasn );
     70 
     71 /**
     72  * Finish receiving PDU data into buffer
     73  *
     74  * @v iscsi		iSCSI session
     75  */
     76 static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
     77 	free ( iscsi->rx_buffer );
     78 	iscsi->rx_buffer = NULL;
     79 }
     80 
     81 /**
     82  * Free iSCSI session
     83  *
     84  * @v refcnt		Reference counter
     85  */
     86 static void iscsi_free ( struct refcnt *refcnt ) {
     87 	struct iscsi_session *iscsi =
     88 		container_of ( refcnt, struct iscsi_session, refcnt );
     89 
     90 	free ( iscsi->target_address );
     91 	free ( iscsi->target_iqn );
     92 	free ( iscsi->initiator_username );
     93 	free ( iscsi->initiator_password );
     94 	free ( iscsi->target_username );
     95 	free ( iscsi->target_password );
     96 	chap_finish ( &iscsi->chap );
     97 	iscsi_rx_buffered_data_done ( iscsi );
     98 	free ( iscsi );
     99 }
    100 
    101 /**
    102  * Open iSCSI transport-layer connection
    103  *
    104  * @v iscsi		iSCSI session
    105  * @ret rc		Return status code
    106  */
    107 static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
    108 	struct sockaddr_tcpip target;
    109 	int rc;
    110 
    111 	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
    112 	assert ( iscsi->rx_state == ISCSI_RX_BHS );
    113 	assert ( iscsi->rx_offset == 0 );
    114 
    115 	/* Open socket */
    116 	memset ( &target, 0, sizeof ( target ) );
    117 	target.st_port = htons ( iscsi->target_port );
    118 	if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
    119 					     ( struct sockaddr * ) &target,
    120 					     iscsi->target_address,
    121 					     NULL ) ) != 0 ) {
    122 		DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
    123 		       iscsi, strerror ( rc ) );
    124 		return rc;
    125 	}
    126 
    127 	/* Enter security negotiation phase */
    128 	iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
    129 			  ISCSI_STATUS_STRINGS_SECURITY );
    130 	if ( iscsi->target_username )
    131 		iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
    132 
    133 	/* Assign fresh initiator task tag */
    134 	iscsi->itt++;
    135 
    136 	/* Initiate login */
    137 	iscsi_start_login ( iscsi );
    138 
    139 	return 0;
    140 }
    141 
    142 /**
    143  * Close iSCSI transport-layer connection
    144  *
    145  * @v iscsi		iSCSI session
    146  * @v rc		Reason for close
    147  *
    148  * Closes the transport-layer connection and resets the session state
    149  * ready to attempt a fresh login.
    150  */
    151 static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
    152 
    153 	/* Close all data transfer interfaces */
    154 	xfer_close ( &iscsi->socket, rc );
    155 
    156 	/* Clear connection status */
    157 	iscsi->status = 0;
    158 
    159 	/* Reset TX and RX state machines */
    160 	iscsi->tx_state = ISCSI_TX_IDLE;
    161 	iscsi->rx_state = ISCSI_RX_BHS;
    162 	iscsi->rx_offset = 0;
    163 
    164 	/* Free any temporary dynamically allocated memory */
    165 	chap_finish ( &iscsi->chap );
    166 	iscsi_rx_buffered_data_done ( iscsi );
    167 }
    168 
    169 /**
    170  * Mark iSCSI SCSI operation as complete
    171  *
    172  * @v iscsi		iSCSI session
    173  * @v rc		Return status code
    174  *
    175  * Note that iscsi_scsi_done() will not close the connection, and must
    176  * therefore be called only when the internal state machines are in an
    177  * appropriate state, otherwise bad things may happen on the next call
    178  * to iscsi_issue().  The general rule is to call iscsi_scsi_done()
    179  * only at the end of receiving a PDU; at this point the TX and RX
    180  * engines should both be idle.
    181  */
    182 static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
    183 
    184 	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
    185 	assert ( iscsi->command != NULL );
    186 
    187 	iscsi->command->rc = rc;
    188 	iscsi->command = NULL;
    189 }
    190 
    191 /****************************************************************************
    192  *
    193  * iSCSI SCSI command issuing
    194  *
    195  */
    196 
    197 /**
    198  * Build iSCSI SCSI command BHS
    199  *
    200  * @v iscsi		iSCSI session
    201  *
    202  * We don't currently support bidirectional commands (i.e. with both
    203  * Data-In and Data-Out segments); these would require providing code
    204  * to generate an AHS, and there doesn't seem to be any need for it at
    205  * the moment.
    206  */
    207 static void iscsi_start_command ( struct iscsi_session *iscsi ) {
    208 	struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
    209 
    210 	assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
    211 
    212 	/* Construct BHS and initiate transmission */
    213 	iscsi_start_tx ( iscsi );
    214 	command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
    215 	command->flags = ( ISCSI_FLAG_FINAL |
    216 			   ISCSI_COMMAND_ATTR_SIMPLE );
    217 	if ( iscsi->command->data_in )
    218 		command->flags |= ISCSI_COMMAND_FLAG_READ;
    219 	if ( iscsi->command->data_out )
    220 		command->flags |= ISCSI_COMMAND_FLAG_WRITE;
    221 	/* lengths left as zero */
    222 	command->lun = iscsi->lun;
    223 	command->itt = htonl ( ++iscsi->itt );
    224 	command->exp_len = htonl ( iscsi->command->data_in_len |
    225 				   iscsi->command->data_out_len );
    226 	command->cmdsn = htonl ( iscsi->cmdsn );
    227 	command->expstatsn = htonl ( iscsi->statsn + 1 );
    228 	memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
    229 	DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
    230 		iscsi, SCSI_CDB_DATA ( command->cdb ),
    231 		( iscsi->command->data_in ? "in" : "out" ),
    232 		( iscsi->command->data_in ?
    233 		  iscsi->command->data_in_len :
    234 		  iscsi->command->data_out_len ) );
    235 }
    236 
    237 /**
    238  * Receive data segment of an iSCSI SCSI response PDU
    239  *
    240  * @v iscsi		iSCSI session
    241  * @v data		Received data
    242  * @v len		Length of received data
    243  * @v remaining		Data remaining after this data
    244  * @ret rc		Return status code
    245  */
    246 static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
    247 				    const void *data, size_t len,
    248 				    size_t remaining ) {
    249 	struct iscsi_bhs_scsi_response *response
    250 		= &iscsi->rx_bhs.scsi_response;
    251 	int sense_offset;
    252 
    253 	/* Capture the sense response code as it floats past, if present */
    254 	sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
    255 	if ( ( sense_offset >= 0 ) && len ) {
    256 		iscsi->command->sense_response =
    257 			* ( ( char * ) data + sense_offset );
    258 	}
    259 
    260 	/* Wait for whole SCSI response to arrive */
    261 	if ( remaining )
    262 		return 0;
    263 
    264 	/* Record SCSI status code */
    265 	iscsi->command->status = response->status;
    266 
    267 	/* Check for errors */
    268 	if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
    269 		return -EIO;
    270 
    271 	/* Mark as completed */
    272 	iscsi_scsi_done ( iscsi, 0 );
    273 	return 0;
    274 }
    275 
    276 /**
    277  * Receive data segment of an iSCSI data-in PDU
    278  *
    279  * @v iscsi		iSCSI session
    280  * @v data		Received data
    281  * @v len		Length of received data
    282  * @v remaining		Data remaining after this data
    283  * @ret rc		Return status code
    284  */
    285 static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
    286 			      const void *data, size_t len,
    287 			      size_t remaining ) {
    288 	struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
    289 	unsigned long offset;
    290 
    291 	/* Copy data to data-in buffer */
    292 	offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
    293 	assert ( iscsi->command != NULL );
    294 	assert ( iscsi->command->data_in );
    295 	assert ( ( offset + len ) <= iscsi->command->data_in_len );
    296 	copy_to_user ( iscsi->command->data_in, offset, data, len );
    297 
    298 	/* Wait for whole SCSI response to arrive */
    299 	if ( remaining )
    300 		return 0;
    301 
    302 	/* Mark as completed if status is present */
    303 	if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
    304 		assert ( ( offset + len ) == iscsi->command->data_in_len );
    305 		assert ( data_in->flags & ISCSI_FLAG_FINAL );
    306 		iscsi->command->status = data_in->status;
    307 		/* iSCSI cannot return an error status via a data-in */
    308 		iscsi_scsi_done ( iscsi, 0 );
    309 	}
    310 
    311 	return 0;
    312 }
    313 
    314 /**
    315  * Receive data segment of an iSCSI R2T PDU
    316  *
    317  * @v iscsi		iSCSI session
    318  * @v data		Received data
    319  * @v len		Length of received data
    320  * @v remaining		Data remaining after this data
    321  * @ret rc		Return status code
    322  */
    323 static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
    324 			  const void *data __unused, size_t len __unused,
    325 			  size_t remaining __unused ) {
    326 	struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
    327 
    328 	/* Record transfer parameters and trigger first data-out */
    329 	iscsi->ttt = ntohl ( r2t->ttt );
    330 	iscsi->transfer_offset = ntohl ( r2t->offset );
    331 	iscsi->transfer_len = ntohl ( r2t->len );
    332 	iscsi_start_data_out ( iscsi, 0 );
    333 
    334 	return 0;
    335 }
    336 
    337 /**
    338  * Build iSCSI data-out BHS
    339  *
    340  * @v iscsi		iSCSI session
    341  * @v datasn		Data sequence number within the transfer
    342  *
    343  */
    344 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
    345 				   unsigned int datasn ) {
    346 	struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
    347 	unsigned long offset;
    348 	unsigned long remaining;
    349 	unsigned long len;
    350 
    351 	/* We always send 512-byte Data-Out PDUs; this removes the
    352 	 * need to worry about the target's MaxRecvDataSegmentLength.
    353 	 */
    354 	offset = datasn * 512;
    355 	remaining = iscsi->transfer_len - offset;
    356 	len = remaining;
    357 	if ( len > 512 )
    358 		len = 512;
    359 
    360 	/* Construct BHS and initiate transmission */
    361 	iscsi_start_tx ( iscsi );
    362 	data_out->opcode = ISCSI_OPCODE_DATA_OUT;
    363 	if ( len == remaining )
    364 		data_out->flags = ( ISCSI_FLAG_FINAL );
    365 	ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
    366 	data_out->lun = iscsi->lun;
    367 	data_out->itt = htonl ( iscsi->itt );
    368 	data_out->ttt = htonl ( iscsi->ttt );
    369 	data_out->expstatsn = htonl ( iscsi->statsn + 1 );
    370 	data_out->datasn = htonl ( datasn );
    371 	data_out->offset = htonl ( iscsi->transfer_offset + offset );
    372 	DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
    373 	       iscsi, datasn, len );
    374 }
    375 
    376 /**
    377  * Complete iSCSI data-out PDU transmission
    378  *
    379  * @v iscsi		iSCSI session
    380  *
    381  */
    382 static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
    383 	struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
    384 
    385 	/* If we haven't reached the end of the sequence, start
    386 	 * sending the next data-out PDU.
    387 	 */
    388 	if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
    389 		iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
    390 }
    391 
    392 /**
    393  * Send iSCSI data-out data segment
    394  *
    395  * @v iscsi		iSCSI session
    396  * @ret rc		Return status code
    397  */
    398 static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
    399 	struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
    400 	struct io_buffer *iobuf;
    401 	unsigned long offset;
    402 	size_t len;
    403 
    404 	offset = ntohl ( data_out->offset );
    405 	len = ISCSI_DATA_LEN ( data_out->lengths );
    406 
    407 	assert ( iscsi->command != NULL );
    408 	assert ( iscsi->command->data_out );
    409 	assert ( ( offset + len ) <= iscsi->command->data_out_len );
    410 
    411 	iobuf = xfer_alloc_iob ( &iscsi->socket, len );
    412 	if ( ! iobuf )
    413 		return -ENOMEM;
    414 
    415 	copy_from_user ( iob_put ( iobuf, len ),
    416 			 iscsi->command->data_out, offset, len );
    417 
    418 	return xfer_deliver_iob ( &iscsi->socket, iobuf );
    419 }
    420 
    421 /****************************************************************************
    422  *
    423  * iSCSI login
    424  *
    425  */
    426 
    427 /**
    428  * Build iSCSI login request strings
    429  *
    430  * @v iscsi		iSCSI session
    431  *
    432  * These are the initial set of strings sent in the first login
    433  * request PDU.  We want the following settings:
    434  *
    435  *     HeaderDigest=None
    436  *     DataDigest=None
    437  *     MaxConnections is irrelevant; we make only one connection anyway
    438  *     InitialR2T=Yes [1]
    439  *     ImmediateData is irrelevant; we never send immediate data
    440  *     MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
    441  *     MaxBurstLength=262144 (default; we don't care) [3]
    442  *     FirstBurstLength=262144 (default; we don't care)
    443  *     DefaultTime2Wait=0 [2]
    444  *     DefaultTime2Retain=0 [2]
    445  *     MaxOutstandingR2T=1
    446  *     DataPDUInOrder=Yes
    447  *     DataSequenceInOrder=Yes
    448  *     ErrorRecoveryLevel=0
    449  *
    450  * [1] InitialR2T has an OR resolution function, so the target may
    451  * force us to use it.  We therefore simplify our logic by always
    452  * using it.
    453  *
    454  * [2] These ensure that we can safely start a new task once we have
    455  * reconnected after a failure, without having to manually tidy up
    456  * after the old one.
    457  *
    458  * [3] We are quite happy to use the RFC-defined default values for
    459  * these parameters, but some targets (notably OpenSolaris)
    460  * incorrectly assume a default value of zero, so we explicitly
    461  * specify the default values.
    462  */
    463 static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
    464 					       void *data, size_t len ) {
    465 	unsigned int used = 0;
    466 	unsigned int i;
    467 	const char *auth_method;
    468 
    469 	if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
    470 		/* Default to allowing no authentication */
    471 		auth_method = "None";
    472 		/* If we have a credential to supply, permit CHAP */
    473 		if ( iscsi->initiator_username )
    474 			auth_method = "CHAP,None";
    475 		/* If we have a credential to check, force CHAP */
    476 		if ( iscsi->target_username )
    477 			auth_method = "CHAP";
    478 		used += ssnprintf ( data + used, len - used,
    479 				    "InitiatorName=%s%c"
    480 				    "TargetName=%s%c"
    481 				    "SessionType=Normal%c"
    482 				    "AuthMethod=%s%c",
    483 				    iscsi_initiator_iqn(), 0,
    484 				    iscsi->target_iqn, 0, 0,
    485 				    auth_method, 0 );
    486 	}
    487 
    488 	if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
    489 		used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
    490 	}
    491 
    492 	if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
    493 		assert ( iscsi->initiator_username != NULL );
    494 		used += ssnprintf ( data + used, len - used,
    495 				    "CHAP_N=%s%cCHAP_R=0x",
    496 				    iscsi->initiator_username, 0 );
    497 		for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
    498 			used += ssnprintf ( data + used, len - used, "%02x",
    499 					    iscsi->chap.response[i] );
    500 		}
    501 		used += ssnprintf ( data + used, len - used, "%c", 0 );
    502 	}
    503 
    504 	if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
    505 		used += ssnprintf ( data + used, len - used,
    506 				    "CHAP_I=%d%cCHAP_C=0x",
    507 				    iscsi->chap_challenge[0], 0 );
    508 		for ( i = 1 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
    509 			used += ssnprintf ( data + used, len - used, "%02x",
    510 					    iscsi->chap_challenge[i] );
    511 		}
    512 		used += ssnprintf ( data + used, len - used, "%c", 0 );
    513 	}
    514 
    515 	if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
    516 		used += ssnprintf ( data + used, len - used,
    517 				    "HeaderDigest=None%c"
    518 				    "DataDigest=None%c"
    519 				    "InitialR2T=Yes%c"
    520 				    "MaxRecvDataSegmentLength=8192%c"
    521 				    "MaxBurstLength=262144%c"
    522 				    "DefaultTime2Wait=0%c"
    523 				    "DefaultTime2Retain=0%c"
    524 				    "MaxOutstandingR2T=1%c"
    525 				    "DataPDUInOrder=Yes%c"
    526 				    "DataSequenceInOrder=Yes%c"
    527 				    "ErrorRecoveryLevel=0%c",
    528 				    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
    529 	}
    530 
    531 	return used;
    532 }
    533 
    534 /**
    535  * Build iSCSI login request BHS
    536  *
    537  * @v iscsi		iSCSI session
    538  */
    539 static void iscsi_start_login ( struct iscsi_session *iscsi ) {
    540 	struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
    541 	int len;
    542 
    543 	/* Construct BHS and initiate transmission */
    544 	iscsi_start_tx ( iscsi );
    545 	request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
    546 			    ISCSI_FLAG_IMMEDIATE );
    547 	request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
    548 			   ISCSI_LOGIN_FLAG_TRANSITION );
    549 	/* version_max and version_min left as zero */
    550 	len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
    551 	ISCSI_SET_LENGTHS ( request->lengths, 0, len );
    552 	request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
    553 					IANA_EN_FEN_SYSTEMS );
    554 	/* isid_iana_qual left as zero */
    555 	request->tsih = htons ( iscsi->tsih );
    556 	request->itt = htonl ( iscsi->itt );
    557 	/* cid left as zero */
    558 	request->cmdsn = htonl ( iscsi->cmdsn );
    559 	request->expstatsn = htonl ( iscsi->statsn + 1 );
    560 }
    561 
    562 /**
    563  * Complete iSCSI login request PDU transmission
    564  *
    565  * @v iscsi		iSCSI session
    566  *
    567  */
    568 static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
    569 
    570 	/* Clear any "strings to send" flags */
    571 	iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
    572 
    573 	/* Free any dynamically allocated storage used for login */
    574 	chap_finish ( &iscsi->chap );
    575 }
    576 
    577 /**
    578  * Transmit data segment of an iSCSI login request PDU
    579  *
    580  * @v iscsi		iSCSI session
    581  * @ret rc		Return status code
    582  *
    583  * For login requests, the data segment consists of the login strings.
    584  */
    585 static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
    586 	struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
    587 	struct io_buffer *iobuf;
    588 	size_t len;
    589 
    590 	len = ISCSI_DATA_LEN ( request->lengths );
    591 	iobuf = xfer_alloc_iob ( &iscsi->socket, len );
    592 	if ( ! iobuf )
    593 		return -ENOMEM;
    594 	iob_put ( iobuf, len );
    595 	iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
    596 	return xfer_deliver_iob ( &iscsi->socket, iobuf );
    597 }
    598 
    599 /**
    600  * Handle iSCSI TargetAddress text value
    601  *
    602  * @v iscsi		iSCSI session
    603  * @v value		TargetAddress value
    604  * @ret rc		Return status code
    605  */
    606 static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
    607 					      const char *value ) {
    608 	char *separator;
    609 
    610 	DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
    611 
    612 	/* Replace target address */
    613 	free ( iscsi->target_address );
    614 	iscsi->target_address = strdup ( value );
    615 	if ( ! iscsi->target_address )
    616 		return -ENOMEM;
    617 
    618 	/* Replace target port */
    619 	iscsi->target_port = htons ( ISCSI_PORT );
    620 	separator = strchr ( iscsi->target_address, ':' );
    621 	if ( separator ) {
    622 		*separator = '\0';
    623 		iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
    624 	}
    625 
    626 	return 0;
    627 }
    628 
    629 /**
    630  * Handle iSCSI AuthMethod text value
    631  *
    632  * @v iscsi		iSCSI session
    633  * @v value		AuthMethod value
    634  * @ret rc		Return status code
    635  */
    636 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
    637 					   const char *value ) {
    638 
    639 	/* If server requests CHAP, send the CHAP_A string */
    640 	if ( strcmp ( value, "CHAP" ) == 0 ) {
    641 		DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
    642 		       iscsi );
    643 		iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
    644 				   ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
    645 	}
    646 
    647 	return 0;
    648 }
    649 
    650 /**
    651  * Handle iSCSI CHAP_A text value
    652  *
    653  * @v iscsi		iSCSI session
    654  * @v value		CHAP_A value
    655  * @ret rc		Return status code
    656  */
    657 static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
    658 				       const char *value ) {
    659 
    660 	/* We only ever offer "5" (i.e. MD5) as an algorithm, so if
    661 	 * the server responds with anything else it is a protocol
    662 	 * violation.
    663 	 */
    664 	if ( strcmp ( value, "5" ) != 0 ) {
    665 		DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
    666 		       iscsi, value );
    667 		return -EPROTO;
    668 	}
    669 
    670 	return 0;
    671 }
    672 
    673 /**
    674  * Handle iSCSI CHAP_I text value
    675  *
    676  * @v iscsi		iSCSI session
    677  * @v value		CHAP_I value
    678  * @ret rc		Return status code
    679  */
    680 static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
    681 				       const char *value ) {
    682 	unsigned int identifier;
    683 	char *endp;
    684 	int rc;
    685 
    686 	/* The CHAP identifier is an integer value */
    687 	identifier = strtoul ( value, &endp, 0 );
    688 	if ( *endp != '\0' ) {
    689 		DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
    690 		       iscsi, value );
    691 		return -EPROTO;
    692 	}
    693 
    694 	/* Prepare for CHAP with MD5 */
    695 	chap_finish ( &iscsi->chap );
    696 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
    697 		DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
    698 		       iscsi, strerror ( rc ) );
    699 		return rc;
    700 	}
    701 
    702 	/* Identifier and secret are the first two components of the
    703 	 * challenge.
    704 	 */
    705 	chap_set_identifier ( &iscsi->chap, identifier );
    706 	if ( iscsi->initiator_password ) {
    707 		chap_update ( &iscsi->chap, iscsi->initiator_password,
    708 			      strlen ( iscsi->initiator_password ) );
    709 	}
    710 
    711 	return 0;
    712 }
    713 
    714 /**
    715  * Handle iSCSI CHAP_C text value
    716  *
    717  * @v iscsi		iSCSI session
    718  * @v value		CHAP_C value
    719  * @ret rc		Return status code
    720  */
    721 static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
    722 				       const char *value ) {
    723 	char buf[3];
    724 	char *endp;
    725 	uint8_t byte;
    726 	unsigned int i;
    727 
    728 	/* Check and strip leading "0x" */
    729 	if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
    730 		DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
    731 		       iscsi, value );
    732 		return -EPROTO;
    733 	}
    734 	value += 2;
    735 
    736 	/* Process challenge an octet at a time */
    737 	for ( ; ( value[0] && value[1] ) ; value += 2 ) {
    738 		memcpy ( buf, value, 2 );
    739 		buf[2] = 0;
    740 		byte = strtoul ( buf, &endp, 16 );
    741 		if ( *endp != '\0' ) {
    742 			DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
    743 			       "byte \"%s\"\n", iscsi, buf );
    744 			return -EPROTO;
    745 		}
    746 		chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
    747 	}
    748 
    749 	/* Build CHAP response */
    750 	DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
    751 	chap_respond ( &iscsi->chap );
    752 	iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
    753 
    754 	/* Send CHAP challenge, if applicable */
    755 	if ( iscsi->target_username ) {
    756 		iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
    757 		/* Generate CHAP challenge data */
    758 		for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
    759 			iscsi->chap_challenge[i] = random();
    760 		}
    761 	}
    762 
    763 	return 0;
    764 }
    765 
    766 /**
    767  * Handle iSCSI CHAP_N text value
    768  *
    769  * @v iscsi		iSCSI session
    770  * @v value		CHAP_N value
    771  * @ret rc		Return status code
    772  */
    773 static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
    774 				       const char *value ) {
    775 
    776 	/* The target username isn't actually involved at any point in
    777 	 * the authentication process; it merely serves to identify
    778 	 * which password the target is using to generate the CHAP
    779 	 * response.  We unnecessarily verify that the username is as
    780 	 * expected, in order to provide mildly helpful diagnostics if
    781 	 * the target is supplying the wrong username/password
    782 	 * combination.
    783 	 */
    784 	if ( iscsi->target_username &&
    785 	     ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
    786 		DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
    787 		       "(wanted \"%s\")\n",
    788 		       iscsi, value, iscsi->target_username );
    789 		return -EACCES;
    790 	}
    791 
    792 	return 0;
    793 }
    794 
    795 /**
    796  * Handle iSCSI CHAP_R text value
    797  *
    798  * @v iscsi		iSCSI session
    799  * @v value		CHAP_R value
    800  * @ret rc		Return status code
    801  */
    802 static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
    803 				       const char *value ) {
    804 	char buf[3];
    805 	char *endp;
    806 	uint8_t byte;
    807 	unsigned int i;
    808 	int rc;
    809 
    810 	/* Generate CHAP response for verification */
    811 	chap_finish ( &iscsi->chap );
    812 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
    813 		DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
    814 		       iscsi, strerror ( rc ) );
    815 		return rc;
    816 	}
    817 	chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
    818 	if ( iscsi->target_password ) {
    819 		chap_update ( &iscsi->chap, iscsi->target_password,
    820 			      strlen ( iscsi->target_password ) );
    821 	}
    822 	chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
    823 		      ( sizeof ( iscsi->chap_challenge ) - 1 ) );
    824 	chap_respond ( &iscsi->chap );
    825 
    826 	/* Check and strip leading "0x" */
    827 	if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
    828 		DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
    829 		       iscsi, value );
    830 		return -EPROTO;
    831 	}
    832 	value += 2;
    833 
    834 	/* Check CHAP response length */
    835 	if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
    836 		DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
    837 		       iscsi );
    838 		return -EPROTO;
    839 	}
    840 
    841 	/* Process response an octet at a time */
    842 	for ( i = 0 ; ( value[0] && value[1] ) ; value += 2, i++ ) {
    843 		memcpy ( buf, value, 2 );
    844 		buf[2] = 0;
    845 		byte = strtoul ( buf, &endp, 16 );
    846 		if ( *endp != '\0' ) {
    847 			DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
    848 			       "byte \"%s\"\n", iscsi, buf );
    849 			return -EPROTO;
    850 		}
    851 		if ( byte != iscsi->chap.response[i] ) {
    852 			DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
    853 			       "response\n", iscsi );
    854 			return -EACCES;
    855 		}
    856 	}
    857 	assert ( i == iscsi->chap.response_len );
    858 
    859 	/* Mark session as authenticated */
    860 	iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
    861 
    862 	return 0;
    863 }
    864 
    865 /** An iSCSI text string that we want to handle */
    866 struct iscsi_string_type {
    867 	/** String key
    868 	 *
    869 	 * This is the portion up to and including the "=" sign,
    870 	 * e.g. "InitiatorName=", "CHAP_A=", etc.
    871 	 */
    872 	const char *key;
    873 	/** Handle iSCSI string value
    874 	 *
    875 	 * @v iscsi		iSCSI session
    876 	 * @v value		iSCSI string value
    877 	 * @ret rc		Return status code
    878 	 */
    879 	int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
    880 };
    881 
    882 /** iSCSI text strings that we want to handle */
    883 static struct iscsi_string_type iscsi_string_types[] = {
    884 	{ "TargetAddress=", iscsi_handle_targetaddress_value },
    885 	{ "AuthMethod=", iscsi_handle_authmethod_value },
    886 	{ "CHAP_A=", iscsi_handle_chap_a_value },
    887 	{ "CHAP_I=", iscsi_handle_chap_i_value },
    888 	{ "CHAP_C=", iscsi_handle_chap_c_value },
    889 	{ "CHAP_N=", iscsi_handle_chap_n_value },
    890 	{ "CHAP_R=", iscsi_handle_chap_r_value },
    891 	{ NULL, NULL }
    892 };
    893 
    894 /**
    895  * Handle iSCSI string
    896  *
    897  * @v iscsi		iSCSI session
    898  * @v string		iSCSI string (in "key=value" format)
    899  * @ret rc		Return status code
    900  */
    901 static int iscsi_handle_string ( struct iscsi_session *iscsi,
    902 				 const char *string ) {
    903 	struct iscsi_string_type *type;
    904 	size_t key_len;
    905 	int rc;
    906 
    907 	for ( type = iscsi_string_types ; type->key ; type++ ) {
    908 		key_len = strlen ( type->key );
    909 		if ( strncmp ( string, type->key, key_len ) != 0 )
    910 			continue;
    911 		DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
    912 		if ( ( rc = type->handle ( iscsi,
    913 					   ( string + key_len ) ) ) != 0 ) {
    914 			DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
    915 			       iscsi, string, strerror ( rc ) );
    916 			return rc;
    917 		}
    918 		return 0;
    919 	}
    920 	DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
    921 	return 0;
    922 }
    923 
    924 /**
    925  * Handle iSCSI strings
    926  *
    927  * @v iscsi		iSCSI session
    928  * @v string		iSCSI string buffer
    929  * @v len		Length of string buffer
    930  * @ret rc		Return status code
    931  */
    932 static int iscsi_handle_strings ( struct iscsi_session *iscsi,
    933 				  const char *strings, size_t len ) {
    934 	size_t string_len;
    935 	int rc;
    936 
    937 	/* Handle each string in turn, taking care not to overrun the
    938 	 * data buffer in case of badly-terminated data.
    939 	 */
    940 	while ( 1 ) {
    941 		string_len = ( strnlen ( strings, len ) + 1 );
    942 		if ( string_len > len )
    943 			break;
    944 		if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
    945 			return rc;
    946 		strings += string_len;
    947 		len -= string_len;
    948 	}
    949 	return 0;
    950 }
    951 
    952 /**
    953  * Receive PDU data into buffer
    954  *
    955  * @v iscsi		iSCSI session
    956  * @v data		Data to receive
    957  * @v len		Length of data
    958  * @ret rc		Return status code
    959  *
    960  * This can be used when the RX PDU type handler wishes to buffer up
    961  * all received data and process the PDU as a single unit.  The caller
    962  * is repsonsible for calling iscsi_rx_buffered_data_done() after
    963  * processing the data.
    964  */
    965 static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
    966 				    const void *data, size_t len ) {
    967 
    968 	/* Allocate buffer on first call */
    969 	if ( ! iscsi->rx_buffer ) {
    970 		iscsi->rx_buffer = malloc ( iscsi->rx_len );
    971 		if ( ! iscsi->rx_buffer )
    972 			return -ENOMEM;
    973 	}
    974 
    975 	/* Copy data to buffer */
    976 	assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
    977 	memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
    978 
    979 	return 0;
    980 }
    981 
    982 /**
    983  * Convert iSCSI response status to return status code
    984  *
    985  * @v status_class	iSCSI status class
    986  * @v status_detail	iSCSI status detail
    987  * @ret rc		Return status code
    988  */
    989 static int iscsi_status_to_rc ( unsigned int status_class,
    990 				unsigned int status_detail ) {
    991 	switch ( status_class ) {
    992 	case ISCSI_STATUS_INITIATOR_ERROR :
    993 		switch ( status_detail ) {
    994 		case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
    995 			return -EACCES;
    996 		case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
    997 			return -EPERM;
    998 		case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
    999 		case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
   1000 			return -ENODEV;
   1001 		default :
   1002 			return -ENOTSUP;
   1003 		}
   1004 	case ISCSI_STATUS_TARGET_ERROR :
   1005 		return -EIO;
   1006 	default :
   1007 		return -EINVAL;
   1008 	}
   1009 }
   1010 
   1011 /**
   1012  * Receive data segment of an iSCSI login response PDU
   1013  *
   1014  * @v iscsi		iSCSI session
   1015  * @v data		Received data
   1016  * @v len		Length of received data
   1017  * @v remaining		Data remaining after this data
   1018  * @ret rc		Return status code
   1019  */
   1020 static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
   1021 				     const void *data, size_t len,
   1022 				     size_t remaining ) {
   1023 	struct iscsi_bhs_login_response *response
   1024 		= &iscsi->rx_bhs.login_response;
   1025 	int rc;
   1026 
   1027 	/* Buffer up the PDU data */
   1028 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
   1029 		DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
   1030 		       iscsi, strerror ( rc ) );
   1031 		return rc;
   1032 	}
   1033 	if ( remaining )
   1034 		return 0;
   1035 
   1036 	/* Process string data and discard string buffer */
   1037 	if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
   1038 					   iscsi->rx_len ) ) != 0 )
   1039 		return rc;
   1040 	iscsi_rx_buffered_data_done ( iscsi );
   1041 
   1042 	/* Check for login redirection */
   1043 	if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
   1044 		DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
   1045 		iscsi_close_connection ( iscsi, 0 );
   1046 		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
   1047 			DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
   1048 			       iscsi, strerror ( rc ) );
   1049 			return rc;
   1050 		}
   1051 		return 0;
   1052 	}
   1053 
   1054 	/* Check for fatal errors */
   1055 	if ( response->status_class != 0 ) {
   1056 		DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
   1057 		       response->status_class, response->status_detail );
   1058 		rc = iscsi_status_to_rc ( response->status_class,
   1059 					  response->status_detail );
   1060 		iscsi->instant_rc = rc;
   1061 		return rc;
   1062 	}
   1063 
   1064 	/* Handle login transitions */
   1065 	if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
   1066 		iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
   1067 				    ISCSI_STATUS_STRINGS_MASK );
   1068 		switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
   1069 		case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
   1070 			iscsi->status |=
   1071 				( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
   1072 				  ISCSI_STATUS_STRINGS_OPERATIONAL );
   1073 			break;
   1074 		case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
   1075 			iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
   1076 			break;
   1077 		default:
   1078 			DBGC ( iscsi, "iSCSI %p got invalid response flags "
   1079 			       "%02x\n", iscsi, response->flags );
   1080 			return -EIO;
   1081 		}
   1082 	}
   1083 
   1084 	/* Send next login request PDU if we haven't reached the full
   1085 	 * feature phase yet.
   1086 	 */
   1087 	if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
   1088 	     ISCSI_STATUS_FULL_FEATURE_PHASE ) {
   1089 		iscsi_start_login ( iscsi );
   1090 		return 0;
   1091 	}
   1092 
   1093 	/* Check that target authentication was successful (if required) */
   1094 	if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
   1095 	     ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
   1096 		DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
   1097 		       "authentication\n", iscsi );
   1098 		return -EPROTO;
   1099 	}
   1100 
   1101 	/* Reset retry count */
   1102 	iscsi->retry_count = 0;
   1103 
   1104 	/* Record TSIH for future reference */
   1105 	iscsi->tsih = ntohl ( response->tsih );
   1106 
   1107 	/* Send the actual SCSI command */
   1108 	iscsi_start_command ( iscsi );
   1109 
   1110 	return 0;
   1111 }
   1112 
   1113 /****************************************************************************
   1114  *
   1115  * iSCSI to socket interface
   1116  *
   1117  */
   1118 
   1119 /**
   1120  * Start up a new TX PDU
   1121  *
   1122  * @v iscsi		iSCSI session
   1123  *
   1124  * This initiates the process of sending a new PDU.  Only one PDU may
   1125  * be in transit at any one time.
   1126  */
   1127 static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
   1128 	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
   1129 
   1130 	/* Initialise TX BHS */
   1131 	memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
   1132 
   1133 	/* Flag TX engine to start transmitting */
   1134 	iscsi->tx_state = ISCSI_TX_BHS;
   1135 }
   1136 
   1137 /**
   1138  * Transmit nothing
   1139  *
   1140  * @v iscsi		iSCSI session
   1141  * @ret rc		Return status code
   1142  */
   1143 static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
   1144 	return 0;
   1145 }
   1146 
   1147 /**
   1148  * Transmit basic header segment of an iSCSI PDU
   1149  *
   1150  * @v iscsi		iSCSI session
   1151  * @ret rc		Return status code
   1152  */
   1153 static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
   1154 	return xfer_deliver_raw ( &iscsi->socket,  &iscsi->tx_bhs,
   1155 				  sizeof ( iscsi->tx_bhs ) );
   1156 }
   1157 
   1158 /**
   1159  * Transmit data segment of an iSCSI PDU
   1160  *
   1161  * @v iscsi		iSCSI session
   1162  * @ret rc		Return status code
   1163  *
   1164  * Handle transmission of part of a PDU data segment.  iscsi::tx_bhs
   1165  * will be valid when this is called.
   1166  */
   1167 static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
   1168 	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
   1169 
   1170 	switch ( common->opcode & ISCSI_OPCODE_MASK ) {
   1171 	case ISCSI_OPCODE_DATA_OUT:
   1172 		return iscsi_tx_data_out ( iscsi );
   1173 	case ISCSI_OPCODE_LOGIN_REQUEST:
   1174 		return iscsi_tx_login_request ( iscsi );
   1175 	default:
   1176 		/* Nothing to send in other states */
   1177 		return 0;
   1178 	}
   1179 }
   1180 
   1181 /**
   1182  * Transmit data padding of an iSCSI PDU
   1183  *
   1184  * @v iscsi		iSCSI session
   1185  * @ret rc		Return status code
   1186  *
   1187  * Handle transmission of any data padding in a PDU data segment.
   1188  * iscsi::tx_bhs will be valid when this is called.
   1189  */
   1190 static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
   1191 	static const char pad[] = { '\0', '\0', '\0' };
   1192 	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
   1193 	size_t pad_len;
   1194 
   1195 	pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
   1196 	if ( ! pad_len )
   1197 		return 0;
   1198 
   1199 	return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
   1200 }
   1201 
   1202 /**
   1203  * Complete iSCSI PDU transmission
   1204  *
   1205  * @v iscsi		iSCSI session
   1206  *
   1207  * Called when a PDU has been completely transmitted and the TX state
   1208  * machine is about to enter the idle state.  iscsi::tx_bhs will be
   1209  * valid for the just-completed PDU when this is called.
   1210  */
   1211 static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
   1212 	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
   1213 
   1214 	switch ( common->opcode & ISCSI_OPCODE_MASK ) {
   1215 	case ISCSI_OPCODE_DATA_OUT:
   1216 		iscsi_data_out_done ( iscsi );
   1217 	case ISCSI_OPCODE_LOGIN_REQUEST:
   1218 		iscsi_login_request_done ( iscsi );
   1219 	default:
   1220 		/* No action */
   1221 		break;
   1222 	}
   1223 }
   1224 
   1225 /**
   1226  * Transmit iSCSI PDU
   1227  *
   1228  * @v iscsi		iSCSI session
   1229  * @v buf		Temporary data buffer
   1230  * @v len		Length of temporary data buffer
   1231  *
   1232  * Constructs data to be sent for the current TX state
   1233  */
   1234 static void iscsi_tx_step ( struct process *process ) {
   1235 	struct iscsi_session *iscsi =
   1236 		container_of ( process, struct iscsi_session, process );
   1237 	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
   1238 	int ( * tx ) ( struct iscsi_session *iscsi );
   1239 	enum iscsi_tx_state next_state;
   1240 	size_t tx_len;
   1241 	int rc;
   1242 
   1243 	/* Select fragment to transmit */
   1244 	while ( 1 ) {
   1245 		switch ( iscsi->tx_state ) {
   1246 		case ISCSI_TX_IDLE:
   1247 			/* Stop processing */
   1248 			return;
   1249 		case ISCSI_TX_BHS:
   1250 			tx = iscsi_tx_bhs;
   1251 			tx_len = sizeof ( iscsi->tx_bhs );
   1252 			next_state = ISCSI_TX_AHS;
   1253 			break;
   1254 		case ISCSI_TX_AHS:
   1255 			tx = iscsi_tx_nothing;
   1256 			tx_len = 0;
   1257 			next_state = ISCSI_TX_DATA;
   1258 			break;
   1259 		case ISCSI_TX_DATA:
   1260 			tx = iscsi_tx_data;
   1261 			tx_len = ISCSI_DATA_LEN ( common->lengths );
   1262 			next_state = ISCSI_TX_DATA_PADDING;
   1263 			break;
   1264 		case ISCSI_TX_DATA_PADDING:
   1265 			tx = iscsi_tx_data_padding;
   1266 			tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
   1267 			next_state = ISCSI_TX_IDLE;
   1268 			break;
   1269 		default:
   1270 			assert ( 0 );
   1271 			return;
   1272 		}
   1273 
   1274 		/* Check for window availability, if needed */
   1275 		if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
   1276 			/* Cannot transmit at this point; stop processing */
   1277 			return;
   1278 		}
   1279 
   1280 		/* Transmit data */
   1281 		if ( ( rc = tx ( iscsi ) ) != 0 ) {
   1282 			DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
   1283 			       iscsi, strerror ( rc ) );
   1284 			return;
   1285 		}
   1286 
   1287 		/* Move to next state */
   1288 		iscsi->tx_state = next_state;
   1289 		if ( next_state == ISCSI_TX_IDLE )
   1290 			iscsi_tx_done ( iscsi );
   1291 	}
   1292 }
   1293 
   1294 /**
   1295  * Receive basic header segment of an iSCSI PDU
   1296  *
   1297  * @v iscsi		iSCSI session
   1298  * @v data		Received data
   1299  * @v len		Length of received data
   1300  * @v remaining		Data remaining after this data
   1301  * @ret rc		Return status code
   1302  *
   1303  * This fills in iscsi::rx_bhs with the data from the BHS portion of
   1304  * the received PDU.
   1305  */
   1306 static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
   1307 			  size_t len, size_t remaining __unused ) {
   1308 	memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
   1309 	if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
   1310 		DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
   1311 			iscsi, iscsi->rx_bhs.common.opcode,
   1312 			ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
   1313 	}
   1314 	return 0;
   1315 }
   1316 
   1317 /**
   1318  * Discard portion of an iSCSI PDU.
   1319  *
   1320  * @v iscsi		iSCSI session
   1321  * @v data		Received data
   1322  * @v len		Length of received data
   1323  * @v remaining		Data remaining after this data
   1324  * @ret rc		Return status code
   1325  *
   1326  * This discards data from a portion of a received PDU.
   1327  */
   1328 static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
   1329 			      const void *data __unused, size_t len __unused,
   1330 			      size_t remaining __unused ) {
   1331 	/* Do nothing */
   1332 	return 0;
   1333 }
   1334 
   1335 /**
   1336  * Receive data segment of an iSCSI PDU
   1337  *
   1338  * @v iscsi		iSCSI session
   1339  * @v data		Received data
   1340  * @v len		Length of received data
   1341  * @v remaining		Data remaining after this data
   1342  * @ret rc		Return status code
   1343  *
   1344  * Handle processing of part of a PDU data segment.  iscsi::rx_bhs
   1345  * will be valid when this is called.
   1346  */
   1347 static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
   1348 			   size_t len, size_t remaining ) {
   1349 	struct iscsi_bhs_common_response *response
   1350 		= &iscsi->rx_bhs.common_response;
   1351 
   1352 	/* Update cmdsn and statsn */
   1353 	iscsi->cmdsn = ntohl ( response->expcmdsn );
   1354 	iscsi->statsn = ntohl ( response->statsn );
   1355 
   1356 	switch ( response->opcode & ISCSI_OPCODE_MASK ) {
   1357 	case ISCSI_OPCODE_LOGIN_RESPONSE:
   1358 		return iscsi_rx_login_response ( iscsi, data, len, remaining );
   1359 	case ISCSI_OPCODE_SCSI_RESPONSE:
   1360 		return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
   1361 	case ISCSI_OPCODE_DATA_IN:
   1362 		return iscsi_rx_data_in ( iscsi, data, len, remaining );
   1363 	case ISCSI_OPCODE_R2T:
   1364 		return iscsi_rx_r2t ( iscsi, data, len, remaining );
   1365 	default:
   1366 		if ( remaining )
   1367 			return 0;
   1368 		DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
   1369 		       response->opcode );
   1370 		return -ENOTSUP;
   1371 	}
   1372 }
   1373 
   1374 /**
   1375  * Receive new data
   1376  *
   1377  * @v socket		Transport layer interface
   1378  * @v data		Received data
   1379  * @v len		Length of received data
   1380  * @ret rc		Return status code
   1381  *
   1382  * This handles received PDUs.  The receive strategy is to fill in
   1383  * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
   1384  * throw away any AHS portion, and then process each part of the data
   1385  * portion as it arrives.  The data processing routine therefore
   1386  * always has a full copy of the BHS available, even for portions of
   1387  * the data in different packets to the BHS.
   1388  */
   1389 static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
   1390 				      const void *data, size_t len ) {
   1391 	struct iscsi_session *iscsi =
   1392 		container_of ( socket, struct iscsi_session, socket );
   1393 	struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
   1394 	int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
   1395 		       size_t len, size_t remaining );
   1396 	enum iscsi_rx_state next_state;
   1397 	size_t frag_len;
   1398 	size_t remaining;
   1399 	int rc;
   1400 
   1401 	while ( 1 ) {
   1402 		switch ( iscsi->rx_state ) {
   1403 		case ISCSI_RX_BHS:
   1404 			rx = iscsi_rx_bhs;
   1405 			iscsi->rx_len = sizeof ( iscsi->rx_bhs );
   1406 			next_state = ISCSI_RX_AHS;
   1407 			break;
   1408 		case ISCSI_RX_AHS:
   1409 			rx = iscsi_rx_discard;
   1410 			iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
   1411 			next_state = ISCSI_RX_DATA;
   1412 			break;
   1413 		case ISCSI_RX_DATA:
   1414 			rx = iscsi_rx_data;
   1415 			iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
   1416 			next_state = ISCSI_RX_DATA_PADDING;
   1417 			break;
   1418 		case ISCSI_RX_DATA_PADDING:
   1419 			rx = iscsi_rx_discard;
   1420 			iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
   1421 			next_state = ISCSI_RX_BHS;
   1422 			break;
   1423 		default:
   1424 			assert ( 0 );
   1425 			return -EINVAL;
   1426 		}
   1427 
   1428 		frag_len = iscsi->rx_len - iscsi->rx_offset;
   1429 		if ( frag_len > len )
   1430 			frag_len = len;
   1431 		remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
   1432 		if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
   1433 			DBGC ( iscsi, "iSCSI %p could not process received "
   1434 			       "data: %s\n", iscsi, strerror ( rc ) );
   1435 			iscsi_close_connection ( iscsi, rc );
   1436 			iscsi_scsi_done ( iscsi, rc );
   1437 			return rc;
   1438 		}
   1439 
   1440 		iscsi->rx_offset += frag_len;
   1441 		data += frag_len;
   1442 		len -= frag_len;
   1443 
   1444 		/* If all the data for this state has not yet been
   1445 		 * received, stay in this state for now.
   1446 		 */
   1447 		if ( iscsi->rx_offset != iscsi->rx_len )
   1448 			return 0;
   1449 
   1450 		iscsi->rx_state = next_state;
   1451 		iscsi->rx_offset = 0;
   1452 	}
   1453 
   1454 	return 0;
   1455 }
   1456 
   1457 /**
   1458  * Handle stream connection closure
   1459  *
   1460  * @v socket		Transport layer interface
   1461  * @v rc		Reason for close
   1462  *
   1463  */
   1464 static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
   1465 	struct iscsi_session *iscsi =
   1466 		container_of ( socket, struct iscsi_session, socket );
   1467 
   1468 	/* Even a graceful close counts as an error for iSCSI */
   1469 	if ( ! rc )
   1470 		rc = -ECONNRESET;
   1471 
   1472 	/* Close session cleanly */
   1473 	iscsi_close_connection ( iscsi, rc );
   1474 
   1475 	/* Retry connection if within the retry limit, otherwise fail */
   1476 	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
   1477 		DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
   1478 		       iscsi, iscsi->retry_count );
   1479 		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
   1480 			DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
   1481 			       iscsi, strerror ( rc ) );
   1482 			iscsi_scsi_done ( iscsi, rc );
   1483 		}
   1484 	} else {
   1485 		DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
   1486 		iscsi->instant_rc = rc;
   1487 		iscsi_scsi_done ( iscsi, rc );
   1488 	}
   1489 }
   1490 
   1491 /**
   1492  * Handle redirection event
   1493  *
   1494  * @v socket		Transport layer interface
   1495  * @v type		Location type
   1496  * @v args		Remaining arguments depend upon location type
   1497  * @ret rc		Return status code
   1498  */
   1499 static int iscsi_vredirect ( struct xfer_interface *socket, int type,
   1500 			     va_list args ) {
   1501 	struct iscsi_session *iscsi =
   1502 		container_of ( socket, struct iscsi_session, socket );
   1503 	va_list tmp;
   1504 	struct sockaddr *peer;
   1505 
   1506 	/* Intercept redirects to a LOCATION_SOCKET and record the IP
   1507 	 * address for the iBFT.  This is a bit of a hack, but avoids
   1508 	 * inventing an ioctl()-style call to retrieve the socket
   1509 	 * address from a data-xfer interface.
   1510 	 */
   1511 	if ( type == LOCATION_SOCKET ) {
   1512 		va_copy ( tmp, args );
   1513 		( void ) va_arg ( tmp, int ); /* Discard "semantics" */
   1514 		peer = va_arg ( tmp, struct sockaddr * );
   1515 		memcpy ( &iscsi->target_sockaddr, peer,
   1516 			 sizeof ( iscsi->target_sockaddr ) );
   1517 		va_end ( tmp );
   1518 	}
   1519 
   1520 	return xfer_vreopen ( socket, type, args );
   1521 }
   1522 
   1523 
   1524 /** iSCSI socket operations */
   1525 static struct xfer_interface_operations iscsi_socket_operations = {
   1526 	.close		= iscsi_socket_close,
   1527 	.vredirect	= iscsi_vredirect,
   1528 	.window		= unlimited_xfer_window,
   1529 	.alloc_iob	= default_xfer_alloc_iob,
   1530 	.deliver_iob	= xfer_deliver_as_raw,
   1531 	.deliver_raw	= iscsi_socket_deliver_raw,
   1532 };
   1533 
   1534 
   1535 /****************************************************************************
   1536  *
   1537  * iSCSI command issuing
   1538  *
   1539  */
   1540 
   1541 /**
   1542  * Issue SCSI command
   1543  *
   1544  * @v scsi		SCSI device
   1545  * @v command		SCSI command
   1546  * @ret rc		Return status code
   1547  */
   1548 static int iscsi_command ( struct scsi_device *scsi,
   1549 			   struct scsi_command *command ) {
   1550 	struct iscsi_session *iscsi =
   1551 		container_of ( scsi->backend, struct iscsi_session, refcnt );
   1552 	int rc;
   1553 
   1554 	/* Abort immediately if we have a recorded permanent failure */
   1555 	if ( iscsi->instant_rc )
   1556 		return iscsi->instant_rc;
   1557 
   1558 	/* Record SCSI command */
   1559 	iscsi->command = command;
   1560 
   1561 	/* Issue command or open connection as appropriate */
   1562 	if ( iscsi->status ) {
   1563 		iscsi_start_command ( iscsi );
   1564 	} else {
   1565 		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
   1566 			iscsi->command = NULL;
   1567 			return rc;
   1568 		}
   1569 	}
   1570 
   1571 	return 0;
   1572 }
   1573 
   1574 /**
   1575  * Shut down iSCSI interface
   1576  *
   1577  * @v scsi		SCSI device
   1578  */
   1579 void iscsi_detach ( struct scsi_device *scsi ) {
   1580 	struct iscsi_session *iscsi =
   1581 		container_of ( scsi->backend, struct iscsi_session, refcnt );
   1582 
   1583 	xfer_nullify ( &iscsi->socket );
   1584 	iscsi_close_connection ( iscsi, 0 );
   1585 	process_del ( &iscsi->process );
   1586 	scsi->command = scsi_detached_command;
   1587 	ref_put ( scsi->backend );
   1588 	scsi->backend = NULL;
   1589 }
   1590 
   1591 /****************************************************************************
   1592  *
   1593  * Instantiator
   1594  *
   1595  */
   1596 
   1597 /** iSCSI root path components (as per RFC4173) */
   1598 enum iscsi_root_path_component {
   1599 	RP_LITERAL = 0,
   1600 	RP_SERVERNAME,
   1601 	RP_PROTOCOL,
   1602 	RP_PORT,
   1603 	RP_LUN,
   1604 	RP_TARGETNAME,
   1605 	NUM_RP_COMPONENTS
   1606 };
   1607 
   1608 /**
   1609  * Parse iSCSI root path
   1610  *
   1611  * @v iscsi		iSCSI session
   1612  * @v root_path		iSCSI root path (as per RFC4173)
   1613  * @ret rc		Return status code
   1614  */
   1615 static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
   1616 				   const char *root_path ) {
   1617 	char rp_copy[ strlen ( root_path ) + 1 ];
   1618 	char *rp_comp[NUM_RP_COMPONENTS];
   1619 	char *rp = rp_copy;
   1620 	int i = 0;
   1621 	int rc;
   1622 
   1623 	/* Split root path into component parts */
   1624 	strcpy ( rp_copy, root_path );
   1625 	while ( 1 ) {
   1626 		rp_comp[i++] = rp;
   1627 		if ( i == NUM_RP_COMPONENTS )
   1628 			break;
   1629 		for ( ; *rp != ':' ; rp++ ) {
   1630 			if ( ! *rp ) {
   1631 				DBGC ( iscsi, "iSCSI %p root path \"%s\" "
   1632 				       "too short\n", iscsi, root_path );
   1633 				return -EINVAL;
   1634 			}
   1635 		}
   1636 		*(rp++) = '\0';
   1637 	}
   1638 
   1639 	/* Use root path components to configure iSCSI session */
   1640 	iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
   1641 	if ( ! iscsi->target_address )
   1642 		return -ENOMEM;
   1643 	iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
   1644 	if ( ! iscsi->target_port )
   1645 		iscsi->target_port = ISCSI_PORT;
   1646 	if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
   1647 		DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
   1648 		       iscsi, rp_comp[RP_LUN] );
   1649 		return rc;
   1650 	}
   1651 	iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
   1652 	if ( ! iscsi->target_iqn )
   1653 		return -ENOMEM;
   1654 
   1655 	return 0;
   1656 }
   1657 
   1658 /**
   1659  * Set iSCSI authentication details
   1660  *
   1661  * @v iscsi		iSCSI session
   1662  * @v initiator_username Initiator username, if any
   1663  * @v initiator_password Initiator password, if any
   1664  * @v target_username	Target username, if any
   1665  * @v target_password	Target password, if any
   1666  * @ret rc		Return status code
   1667  */
   1668 static int iscsi_set_auth ( struct iscsi_session *iscsi,
   1669 			    const char *initiator_username,
   1670 			    const char *initiator_password,
   1671 			    const char *target_username,
   1672 			    const char *target_password ) {
   1673 
   1674 	/* Check for initiator or target credentials */
   1675 	if ( initiator_username || initiator_password ||
   1676 	     target_username || target_password ) {
   1677 
   1678 		/* We must have at least an initiator username+password */
   1679 		if ( ! ( initiator_username && initiator_password ) )
   1680 			goto invalid_auth;
   1681 
   1682 		/* Store initiator credentials */
   1683 		iscsi->initiator_username = strdup ( initiator_username );
   1684 		if ( ! iscsi->initiator_username )
   1685 			return -ENOMEM;
   1686 		iscsi->initiator_password = strdup ( initiator_password );
   1687 		if ( ! iscsi->initiator_password )
   1688 			return -ENOMEM;
   1689 
   1690 		/* Check for target credentials */
   1691 		if ( target_username || target_password ) {
   1692 
   1693 			/* We must have target username+password */
   1694 			if ( ! ( target_username && target_password ) )
   1695 				goto invalid_auth;
   1696 
   1697 			/* Store target credentials */
   1698 			iscsi->target_username = strdup ( target_username );
   1699 			if ( ! iscsi->target_username )
   1700 				return -ENOMEM;
   1701 			iscsi->target_password = strdup ( target_password );
   1702 			if ( ! iscsi->target_password )
   1703 				return -ENOMEM;
   1704 		}
   1705 	}
   1706 
   1707 	return 0;
   1708 
   1709  invalid_auth:
   1710 	DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
   1711 	       "%sname,%spw, target %sname,%spw\n", iscsi,
   1712 	       ( initiator_username ? "" : "no " ),
   1713 	       ( initiator_password ? "" : "no " ),
   1714 	       ( target_username ? "" : "no " ),
   1715 	       ( target_password ? "" : "no " ) );
   1716 	return -EINVAL;
   1717 }
   1718 
   1719 /**
   1720  * Attach iSCSI interface
   1721  *
   1722  * @v scsi		SCSI device
   1723  * @v root_path		iSCSI root path (as per RFC4173)
   1724  * @ret rc		Return status code
   1725  */
   1726 int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
   1727 	struct iscsi_session *iscsi;
   1728 	int rc;
   1729 
   1730 	/* Allocate and initialise structure */
   1731 	iscsi = zalloc ( sizeof ( *iscsi ) );
   1732 	if ( ! iscsi )
   1733 		return -ENOMEM;
   1734 	iscsi->refcnt.free = iscsi_free;
   1735 	xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt );
   1736 	process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
   1737 
   1738 	/* Parse root path */
   1739 	if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
   1740 		goto err;
   1741 	/* Set fields not specified by root path */
   1742 	if ( ( rc = iscsi_set_auth ( iscsi,
   1743 				     iscsi_initiator_username,
   1744 				     iscsi_initiator_password,
   1745 				     iscsi_target_username,
   1746 				     iscsi_target_password ) ) != 0 )
   1747 		goto err;
   1748 
   1749 	/* Sanity checks */
   1750 	if ( ! iscsi->target_address ) {
   1751 		DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
   1752 		       iscsi );
   1753 		rc = -ENOTSUP;
   1754 		goto err;
   1755 	}
   1756 	if ( ! iscsi->target_iqn ) {
   1757 		DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
   1758 		       iscsi, root_path );
   1759 		rc = -EINVAL;
   1760 		goto err;
   1761 	}
   1762 
   1763 	/* Attach parent interface, mortalise self, and return */
   1764 	scsi->backend = ref_get ( &iscsi->refcnt );
   1765 	scsi->command = iscsi_command;
   1766 	ref_put ( &iscsi->refcnt );
   1767 	return 0;
   1768 
   1769  err:
   1770 	ref_put ( &iscsi->refcnt );
   1771 	return rc;
   1772 }
   1773 
   1774 /****************************************************************************
   1775  *
   1776  * Settings
   1777  *
   1778  */
   1779 
   1780 /** iSCSI initiator IQN setting */
   1781 struct setting initiator_iqn_setting __setting = {
   1782 	.name = "initiator-iqn",
   1783 	.description = "iSCSI initiator name",
   1784 	.tag = DHCP_ISCSI_INITIATOR_IQN,
   1785 	.type = &setting_type_string,
   1786 };
   1787 
   1788 /** iSCSI reverse username setting */
   1789 struct setting reverse_username_setting __setting = {
   1790 	.name = "reverse-username",
   1791 	.description = "Reverse user name",
   1792 	.tag = DHCP_EB_REVERSE_USERNAME,
   1793 	.type = &setting_type_string,
   1794 };
   1795 
   1796 /** iSCSI reverse password setting */
   1797 struct setting reverse_password_setting __setting = {
   1798 	.name = "reverse-password",
   1799 	.description = "Reverse password",
   1800 	.tag = DHCP_EB_REVERSE_PASSWORD,
   1801 	.type = &setting_type_string,
   1802 };
   1803 
   1804 /** An iSCSI string setting */
   1805 struct iscsi_string_setting {
   1806 	/** Setting */
   1807 	struct setting *setting;
   1808 	/** String to update */
   1809 	char **string;
   1810 	/** String prefix */
   1811 	const char *prefix;
   1812 };
   1813 
   1814 /** iSCSI string settings */
   1815 static struct iscsi_string_setting iscsi_string_settings[] = {
   1816 	{
   1817 		.setting = &initiator_iqn_setting,
   1818 		.string = &iscsi_explicit_initiator_iqn,
   1819 		.prefix = "",
   1820 	},
   1821 	{
   1822 		.setting = &username_setting,
   1823 		.string = &iscsi_initiator_username,
   1824 		.prefix = "",
   1825 	},
   1826 	{
   1827 		.setting = &password_setting,
   1828 		.string = &iscsi_initiator_password,
   1829 		.prefix = "",
   1830 	},
   1831 	{
   1832 		.setting = &reverse_username_setting,
   1833 		.string = &iscsi_target_username,
   1834 		.prefix = "",
   1835 	},
   1836 	{
   1837 		.setting = &reverse_password_setting,
   1838 		.string = &iscsi_target_password,
   1839 		.prefix = "",
   1840 	},
   1841 	{
   1842 		.setting = &hostname_setting,
   1843 		.string = &iscsi_default_initiator_iqn,
   1844 		.prefix = "iqn.2000-01.org.etherboot:",
   1845 	},
   1846 };
   1847 
   1848 /**
   1849  * Apply iSCSI setting
   1850  *
   1851  * @v setting		iSCSI string setting
   1852  * @ret rc		Return status code
   1853  */
   1854 static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
   1855 	size_t prefix_len;
   1856 	int setting_len;
   1857 	size_t len;
   1858 	int check_len;
   1859 	char *p;
   1860 
   1861 	/* Free old string */
   1862 	free ( *setting->string );
   1863 	*setting->string = NULL;
   1864 
   1865 	/* Allocate new string */
   1866 	prefix_len = strlen ( setting->prefix );
   1867 	setting_len = fetch_setting_len ( NULL, setting->setting );
   1868 	if ( setting_len < 0 ) {
   1869 		/* Missing settings are not errors; leave strings as NULL */
   1870 		return 0;
   1871 	}
   1872 	len = ( prefix_len + setting_len + 1 );
   1873 	p = *setting->string = malloc ( len );
   1874 	if ( ! p )
   1875 		return -ENOMEM;
   1876 
   1877 	/* Fill new string */
   1878 	strcpy ( p, setting->prefix );
   1879 	check_len = fetch_string_setting ( NULL, setting->setting,
   1880 					   ( p + prefix_len ),
   1881 					   ( len - prefix_len ) );
   1882 	assert ( check_len == setting_len );
   1883 
   1884 	return 0;
   1885 }
   1886 
   1887 /**
   1888  * Apply iSCSI settings
   1889  *
   1890  * @ret rc		Return status code
   1891  */
   1892 static int apply_iscsi_settings ( void ) {
   1893 	struct iscsi_string_setting *setting;
   1894 	unsigned int i;
   1895 	int rc;
   1896 
   1897 	for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
   1898 			    sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
   1899 		setting = &iscsi_string_settings[i];
   1900 		if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
   1901 			DBG ( "iSCSI could not apply setting %s\n",
   1902 			      setting->setting->name );
   1903 			return rc;
   1904 		}
   1905 	}
   1906 
   1907 	return 0;
   1908 }
   1909 
   1910 /** iSCSI settings applicator */
   1911 struct settings_applicator iscsi_settings_applicator __settings_applicator = {
   1912 	.apply = apply_iscsi_settings,
   1913 };
   1914 
   1915 /****************************************************************************
   1916  *
   1917  * Initiator name
   1918  *
   1919  */
   1920 
   1921 /**
   1922  * Get iSCSI initiator IQN
   1923  *
   1924  * @v iscsi		iSCSI session
   1925  * @ret rc		Return status code
   1926  */
   1927 const char * iscsi_initiator_iqn ( void ) {
   1928 
   1929 	if ( iscsi_explicit_initiator_iqn )
   1930 		return iscsi_explicit_initiator_iqn;
   1931 	if ( iscsi_default_initiator_iqn )
   1932 		return iscsi_default_initiator_iqn;
   1933 	return "iqn.2000-09.org.etherboot:UNKNOWN";
   1934 }
   1935