Home | History | Annotate | Download | only in tcp

Lines Matching refs:iscsi

38 #include <gpxe/iscsi.h>
42 * iSCSI protocol
46 FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
48 /** iSCSI initiator name (explicitly specified) */
51 /** Default iSCSI initiator name (constructed from hostname) */
54 /** iSCSI initiator username */
57 /** iSCSI initiator password */
60 /** iSCSI target username */
63 /** iSCSI target password */
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,
74 * @v iscsi iSCSI session
76 static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
77 free ( iscsi->rx_buffer );
78 iscsi->rx_buffer = NULL;
82 * Free iSCSI session
87 struct iscsi_session *iscsi =
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 );
102 * Open iSCSI transport-layer connection
104 * @v iscsi iSCSI session
107 static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
111 assert ( iscsi->tx_state == ISCSI_TX_IDLE );
112 assert ( iscsi->rx_state == ISCSI_RX_BHS );
113 assert ( iscsi->rx_offset == 0 );
117 target.st_port = htons ( iscsi->target_port );
118 if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
120 iscsi->target_address,
122 DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
123 iscsi, strerror ( rc ) );
128 iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
130 if ( iscsi->target_username )
131 iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
134 iscsi->itt++;
137 iscsi_start_login ( iscsi );
143 * Close iSCSI transport-layer connection
145 * @v iscsi iSCSI session
151 static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
154 xfer_close ( &iscsi->socket, rc );
157 iscsi->status = 0;
160 iscsi->tx_state = ISCSI_TX_IDLE;
161 iscsi->rx_state = ISCSI_RX_BHS;
162 iscsi->rx_offset = 0;
165 chap_finish ( &iscsi->chap );
166 iscsi_rx_buffered_data_done ( iscsi );
170 * Mark iSCSI SCSI operation as complete
172 * @v iscsi iSCSI session
182 static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
184 assert ( iscsi->tx_state == ISCSI_TX_IDLE );
185 assert ( iscsi->command != NULL );
187 iscsi->command->rc = rc;
188 iscsi->command = NULL;
193 * iSCSI SCSI command issuing
198 * Build iSCSI SCSI command BHS
200 * @v iscsi iSCSI session
207 static void iscsi_start_command ( struct iscsi_session *iscsi ) {
208 struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
210 assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
213 iscsi_start_tx ( iscsi );
217 if ( iscsi->command->data_in )
219 if ( iscsi->command->data_out )
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 ) );
238 * Receive data segment of an iSCSI SCSI response PDU
240 * @v iscsi iSCSI session
246 static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
250 = &iscsi->rx_bhs.scsi_response;
254 sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
256 iscsi->command->sense_response =
265 iscsi->command->status = response->status;
272 iscsi_scsi_done ( iscsi, 0 );
277 * Receive data segment of an iSCSI data-in PDU
279 * @v iscsi iSCSI session
285 static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
288 struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
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 );
304 assert ( ( offset + len ) == iscsi->command->data_in_len );
306 iscsi->command->status = data_in->status;
307 /* iSCSI cannot return an error status via a data-in */
308 iscsi_scsi_done ( iscsi, 0 );
315 * Receive data segment of an iSCSI R2T PDU
317 * @v iscsi iSCSI session
323 static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
326 struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
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 );
338 * Build iSCSI data-out BHS
340 * @v iscsi iSCSI session
344 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
346 struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
355 remaining = iscsi->transfer_len - offset;
361 iscsi_start_tx ( iscsi );
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 );
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 );
377 * Complete iSCSI data-out PDU transmission
379 * @v iscsi iSCSI session
382 static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
383 struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
389 iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
393 * Send iSCSI data-out data segment
395 * @v iscsi iSCSI session
398 static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
399 struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
407 assert ( iscsi->command != NULL );
408 assert ( iscsi->command->data_out );
409 assert ( ( offset + len ) <= iscsi->command->data_out_len );
411 iobuf = xfer_alloc_iob ( &iscsi->socket, len );
416 iscsi->command->data_out, offset, len );
418 return xfer_deliver_iob ( &iscsi->socket, iobuf );
423 * iSCSI login
428 * Build iSCSI login request strings
430 * @v iscsi iSCSI session
463 static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
469 if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
473 if ( iscsi->initiator_username )
476 if ( iscsi->target_username )
484 iscsi->target_iqn, 0, 0,
488 if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
492 if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
493 assert ( iscsi->initiator_username != NULL );
496 iscsi->initiator_username, 0 );
497 for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
499 iscsi->chap.response[i] );
504 if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
507 iscsi->chap_challenge[0], 0 );
508 for ( i = 1 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
510 iscsi->chap_challenge[i] );
515 if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
535 * Build iSCSI login request BHS
537 * @v iscsi iSCSI session
539 static void iscsi_start_login ( struct iscsi_session *iscsi ) {
540 struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
544 iscsi_start_tx ( iscsi );
547 request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
550 len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
555 request->tsih = htons ( iscsi->tsih );
556 request->itt = htonl ( iscsi->itt );
558 request->cmdsn = htonl ( iscsi->cmdsn );
559 request->expstatsn = htonl ( iscsi->statsn + 1 );
563 * Complete iSCSI login request PDU transmission
565 * @v iscsi iSCSI session
568 static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
571 iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
574 chap_finish ( &iscsi->chap );
578 * Transmit data segment of an iSCSI login request PDU
580 * @v iscsi iSCSI session
585 static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
586 struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
591 iobuf = xfer_alloc_iob ( &iscsi->socket, len );
595 iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
596 return xfer_deliver_iob ( &iscsi->socket, iobuf );
600 * Handle iSCSI TargetAddress text value
602 * @v iscsi iSCSI session
606 static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
610 DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
613 free ( iscsi->target_address );
614 iscsi->target_address = strdup ( value );
615 if ( ! iscsi->target_address )
619 iscsi->target_port = htons ( ISCSI_PORT );
620 separator = strchr ( iscsi->target_address, ':' );
623 iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
630 * Handle iSCSI AuthMethod text value
632 * @v iscsi iSCSI session
636 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
641 DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
642 iscsi );
643 iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
651 * Handle iSCSI CHAP_A text value
653 * @v iscsi iSCSI session
657 static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
665 DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
666 iscsi, value );
674 * Handle iSCSI CHAP_I text value
676 * @v iscsi iSCSI session
680 static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
689 DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
690 iscsi, value );
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 ) );
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 ) );
715 * Handle iSCSI CHAP_C text value
717 * @v iscsi iSCSI session
721 static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
730 DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
731 iscsi, value );
742 DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
743 "byte \"%s\"\n", iscsi, buf );
746 chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
750 DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
751 chap_respond ( &iscsi->chap );
752 iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
755 if ( iscsi->target_username ) {
756 iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
758 for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
759 iscsi->chap_challenge[i] = random();
767 * Handle iSCSI CHAP_N text value
769 * @v iscsi iSCSI session
773 static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
784 if ( iscsi->target_username &&
785 ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
786 DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
788 iscsi, value, iscsi->target_username );
796 * Handle iSCSI CHAP_R text value
798 * @v iscsi iSCSI session
802 static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
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 ) );
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 ) );
822 chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
823 ( sizeof ( iscsi->chap_challenge ) - 1 ) );
824 chap_respond ( &iscsi->chap );
828 DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
829 iscsi, value );
835 if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
836 DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
837 iscsi );
847 DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
848 "byte \"%s\"\n", iscsi, buf );
851 if ( byte != iscsi->chap.response[i] ) {
852 DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
853 "response\n", iscsi );
857 assert ( i == iscsi->chap.response_len );
860 iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
865 /** An iSCSI text string that we want to handle */
873 /** Handle iSCSI string value
875 * @v iscsi iSCSI session
876 * @v value iSCSI string value
879 int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
882 /** iSCSI text strings that we want to handle */
895 * Handle iSCSI string
897 * @v iscsi iSCSI session
898 * @v string iSCSI string (in "key=value" format)
901 static int iscsi_handle_string ( struct iscsi_session *iscsi,
911 DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
912 if ( ( rc = type->handle ( iscsi,
914 DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
915 iscsi, string, strerror ( rc ) );
920 DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
925 * Handle iSCSI strings
927 * @v iscsi iSCSI session
928 * @v string iSCSI string buffer
932 static int iscsi_handle_strings ( struct iscsi_session *iscsi,
944 if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
955 * @v iscsi iSCSI session
965 static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
969 if ( ! iscsi->rx_buffer ) {
970 iscsi->rx_buffer = malloc ( iscsi->rx_len );
971 if ( ! iscsi->rx_buffer )
976 assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
977 memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
983 * Convert iSCSI response status to return status code
985 * @v status_class iSCSI status class
986 * @v status_detail iSCSI status detail
1012 * Receive data segment of an iSCSI login response PDU
1014 * @v iscsi iSCSI session
1020 static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
1024 = &iscsi->rx_bhs.login_response;
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 ) );
1037 if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
1038 iscsi->rx_len ) ) != 0 )
1040 iscsi_rx_buffered_data_done ( iscsi );
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 ) );
1056 DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
1060 iscsi->instant_rc = rc;
1066 iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
1070 iscsi->status |=
1075 iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
1078 DBGC ( iscsi, "iSCSI %p got invalid response flags "
1079 "%02x\n", iscsi, response->flags );
1087 if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
1089 iscsi_start_login ( iscsi );
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 );
1102 iscsi->retry_count = 0;
1105 iscsi->tsih = ntohl ( response->tsih );
1108 iscsi_start_command ( iscsi );
1115 * iSCSI to socket interface
1122 * @v iscsi iSCSI session
1127 static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
1128 assert ( iscsi->tx_state == ISCSI_TX_IDLE );
1131 memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
1134 iscsi->tx_state = ISCSI_TX_BHS;
1140 * @v iscsi iSCSI session
1143 static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
1148 * Transmit basic header segment of an iSCSI PDU
1150 * @v iscsi iSCSI session
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 ) );
1159 * Transmit data segment of an iSCSI PDU
1161 * @v iscsi iSCSI session
1164 * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
1167 static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
1168 struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1172 return iscsi_tx_data_out ( iscsi );
1174 return iscsi_tx_login_request ( iscsi );
1182 * Transmit data padding of an iSCSI PDU
1184 * @v iscsi iSCSI session
1188 * iscsi::tx_bhs will be valid when this is called.
1190 static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
1192 struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1199 return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
1203 * Complete iSCSI PDU transmission
1205 * @v iscsi iSCSI session
1208 * machine is about to enter the idle state. iscsi::tx_bhs will be
1211 static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
1212 struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1216 iscsi_data_out_done ( iscsi );
1218 iscsi_login_request_done ( iscsi );
1226 * Transmit iSCSI PDU
1228 * @v iscsi iSCSI session
1235 struct iscsi_session *iscsi =
1237 struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1238 int ( * tx ) ( struct iscsi_session *iscsi );
1245 switch ( iscsi->tx_state ) {
1251 tx_len = sizeof ( iscsi->tx_bhs );
1275 if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
1281 if ( ( rc = tx ( iscsi ) ) != 0 ) {
1282 DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
1283 iscsi, strerror ( rc ) );
1288 iscsi->tx_state = next_state;
1290 iscsi_tx_done ( iscsi );
1295 * Receive basic header segment of an iSCSI PDU
1297 * @v iscsi iSCSI session
1303 * This fills in iscsi::rx_bhs with the data from the BHS portion of
1306 static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
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 ) );
1318 * Discard portion of an iSCSI PDU.
1320 * @v iscsi iSCSI session
1328 static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
1336 * Receive data segment of an iSCSI PDU
1338 * @v iscsi iSCSI session
1344 * Handle processing of part of a PDU data segment. iscsi::rx_bhs
1347 static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
1350 = &iscsi->rx_bhs.common_response;
1353 iscsi->cmdsn = ntohl ( response->expcmdsn );
1354 iscsi->statsn = ntohl ( response->statsn );
1358 return iscsi_rx_login_response ( iscsi, data, len, remaining );
1360 return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
1362 return iscsi_rx_data_in ( iscsi, data, len, remaining );
1364 return iscsi_rx_r2t ( iscsi, data, len, remaining );
1368 DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
1383 * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
1391 struct iscsi_session *iscsi =
1393 struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
1394 int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
1402 switch ( iscsi->rx_state ) {
1405 iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1410 iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1415 iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1420 iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1428 frag_len = iscsi->rx_len - iscsi->rx_offset;
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 );
1440 iscsi->rx_offset += frag_len;
1447 if ( iscsi->rx_offset != iscsi->rx_len )
1450 iscsi->rx_state = next_state;
1451 iscsi->rx_offset = 0;
1465 struct iscsi_session *iscsi =
1468 /* Even a graceful close counts as an error for iSCSI */
1473 iscsi_close_connection ( iscsi, rc );
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 );
1485 DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
1486 iscsi->instant_rc = rc;
1487 iscsi_scsi_done ( iscsi, rc );
1501 struct iscsi_session *iscsi =
1515 memcpy ( &iscsi->target_sockaddr, peer,
1516 sizeof ( iscsi->target_sockaddr ) );
1524 /** iSCSI socket operations */
1537 * iSCSI command issuing
1550 struct iscsi_session *iscsi =
1555 if ( iscsi->instant_rc )
1556 return iscsi->instant_rc;
1559 iscsi->command = command;
1562 if ( iscsi->status ) {
1563 iscsi_start_command ( iscsi );
1565 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1566 iscsi->command = NULL;
1575 * Shut down iSCSI interface
1580 struct iscsi_session *iscsi =
1583 xfer_nullify ( &iscsi->socket );
1584 iscsi_close_connection ( iscsi, 0 );
1585 process_del ( &iscsi->process );
1597 /** iSCSI root path components (as per RFC4173) */
1609 * Parse iSCSI root path
1611 * @v iscsi iSCSI session
1612 * @v root_path iSCSI root path (as per RFC4173)
1615 static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
1631 DBGC ( iscsi, "iSCSI %p root path \"%s\" "
1632 "too short\n", iscsi, root_path );
1639 /* Use root path components to configure iSCSI session */
1640 iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
1641 if ( ! iscsi->target_address )
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] );
1651 iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
1652 if ( ! iscsi->target_iqn )
1659 * Set iSCSI authentication details
1661 * @v iscsi iSCSI session
1668 static int iscsi_set_auth ( struct iscsi_session *iscsi,
1683 iscsi->initiator_username = strdup ( initiator_username );
1684 if ( ! iscsi->initiator_username )
1686 iscsi->initiator_password = strdup ( initiator_password );
1687 if ( ! iscsi->initiator_password )
1698 iscsi->target_username = strdup ( target_username );
1699 if ( ! iscsi->target_username )
1701 iscsi->target_password = strdup ( target_password );
1702 if ( ! iscsi->target_password )
1710 DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
1711 "%sname,%spw, target %sname,%spw\n", iscsi,
1720 * Attach iSCSI interface
1723 * @v root_path iSCSI root path (as per RFC4173)
1727 struct iscsi_session *iscsi;
1731 iscsi = zalloc ( sizeof ( *iscsi ) );
1732 if ( ! iscsi )
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 );
1739 if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
1742 if ( ( rc = iscsi_set_auth ( iscsi,
1750 if ( ! iscsi->target_address ) {
1751 DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
1752 iscsi );
1756 if ( ! iscsi->target_iqn ) {
1757 DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
1758 iscsi, root_path );
1764 scsi->backend = ref_get ( &iscsi->refcnt );
1766 iscsi->refcnt );
1770 ref_put ( &iscsi->refcnt );
1780 /** iSCSI initiator IQN setting */
1783 .description = "iSCSI initiator name",
1788 /** iSCSI reverse username setting */
1796 /** iSCSI reverse password setting */
1804 /** An iSCSI string setting */
1814 /** iSCSI string settings */
1849 * Apply iSCSI setting
1851 * @v setting iSCSI string setting
1888 * Apply iSCSI settings
1901 DBG ( "iSCSI could not apply setting %s\n",
1910 /** iSCSI settings applicator */
1922 * Get iSCSI initiator IQN
1924 * @v iscsi iSCSI session