2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
34 #include <ipxe/vsprintf.h>
35 #include <ipxe/socket.h>
36 #include <ipxe/iobuf.h>
38 #include <ipxe/xfer.h>
39 #include <ipxe/open.h>
40 #include <ipxe/scsi.h>
41 #include <ipxe/process.h>
42 #include <ipxe/uaccess.h>
43 #include <ipxe/tcpip.h>
44 #include <ipxe/settings.h>
45 #include <ipxe/features.h>
46 #include <ipxe/base16.h>
47 #include <ipxe/base64.h>
48 #include <ipxe/ibft.h>
49 #include <ipxe/iscsi.h>
57 FEATURE ( FEATURE_PROTOCOL
, "iSCSI", DHCP_EB_FEATURE_ISCSI
, 1 );
59 /* Disambiguate the various error causes */
60 #define EACCES_INCORRECT_TARGET_USERNAME \
61 __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_USERNAME )
62 #define EINFO_EACCES_INCORRECT_TARGET_USERNAME \
63 __einfo_uniqify ( EINFO_EACCES, 0x01, "Incorrect target username" )
64 #define EACCES_INCORRECT_TARGET_PASSWORD \
65 __einfo_error ( EINFO_EACCES_INCORRECT_TARGET_PASSWORD )
66 #define EINFO_EACCES_INCORRECT_TARGET_PASSWORD \
67 __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect target password" )
68 #define EINVAL_ROOT_PATH_TOO_SHORT \
69 __einfo_error ( EINFO_EINVAL_ROOT_PATH_TOO_SHORT )
70 #define EINFO_EINVAL_ROOT_PATH_TOO_SHORT \
71 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Root path too short" )
72 #define EINVAL_BAD_CREDENTIAL_MIX \
73 __einfo_error ( EINFO_EINVAL_BAD_CREDENTIAL_MIX )
74 #define EINFO_EINVAL_BAD_CREDENTIAL_MIX \
75 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Bad credential mix" )
76 #define EINVAL_NO_ROOT_PATH \
77 __einfo_error ( EINFO_EINVAL_NO_ROOT_PATH )
78 #define EINFO_EINVAL_NO_ROOT_PATH \
79 __einfo_uniqify ( EINFO_EINVAL, 0x03, "No root path" )
80 #define EINVAL_NO_TARGET_IQN \
81 __einfo_error ( EINFO_EINVAL_NO_TARGET_IQN )
82 #define EINFO_EINVAL_NO_TARGET_IQN \
83 __einfo_uniqify ( EINFO_EINVAL, 0x04, "No target IQN" )
84 #define EINVAL_NO_INITIATOR_IQN \
85 __einfo_error ( EINFO_EINVAL_NO_INITIATOR_IQN )
86 #define EINFO_EINVAL_NO_INITIATOR_IQN \
87 __einfo_uniqify ( EINFO_EINVAL, 0x05, "No initiator IQN" )
88 #define EIO_TARGET_UNAVAILABLE \
89 __einfo_error ( EINFO_EIO_TARGET_UNAVAILABLE )
90 #define EINFO_EIO_TARGET_UNAVAILABLE \
91 __einfo_uniqify ( EINFO_EIO, 0x01, "Target not currently operational" )
92 #define EIO_TARGET_NO_RESOURCES \
93 __einfo_error ( EINFO_EIO_TARGET_NO_RESOURCES )
94 #define EINFO_EIO_TARGET_NO_RESOURCES \
95 __einfo_uniqify ( EINFO_EIO, 0x02, "Target out of resources" )
96 #define ENOTSUP_INITIATOR_STATUS \
97 __einfo_error ( EINFO_ENOTSUP_INITIATOR_STATUS )
98 #define EINFO_ENOTSUP_INITIATOR_STATUS \
99 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported initiator status" )
100 #define ENOTSUP_OPCODE \
101 __einfo_error ( EINFO_ENOTSUP_OPCODE )
102 #define EINFO_ENOTSUP_OPCODE \
103 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported opcode" )
104 #define ENOTSUP_DISCOVERY \
105 __einfo_error ( EINFO_ENOTSUP_DISCOVERY )
106 #define EINFO_ENOTSUP_DISCOVERY \
107 __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Discovery not supported" )
108 #define ENOTSUP_TARGET_STATUS \
109 __einfo_error ( EINFO_ENOTSUP_TARGET_STATUS )
110 #define EINFO_ENOTSUP_TARGET_STATUS \
111 __einfo_uniqify ( EINFO_ENOTSUP, 0x04, "Unsupported target status" )
112 #define ENOTSUP_NOP_IN \
113 __einfo_error ( EINFO_ENOTSUP_NOP_IN )
114 #define EINFO_ENOTSUP_NOP_IN \
115 __einfo_uniqify ( EINFO_ENOTSUP, 0x05, "Unsupported NOP-In received" )
116 #define EPERM_INITIATOR_AUTHENTICATION \
117 __einfo_error ( EINFO_EPERM_INITIATOR_AUTHENTICATION )
118 #define EINFO_EPERM_INITIATOR_AUTHENTICATION \
119 __einfo_uniqify ( EINFO_EPERM, 0x01, "Initiator authentication failed" )
120 #define EPERM_INITIATOR_AUTHORISATION \
121 __einfo_error ( EINFO_EPERM_INITIATOR_AUTHORISATION )
122 #define EINFO_EPERM_INITIATOR_AUTHORISATION \
123 __einfo_uniqify ( EINFO_EPERM, 0x02, "Initiator not authorised" )
124 #define EPROTO_INVALID_CHAP_ALGORITHM \
125 __einfo_error ( EINFO_EPROTO_INVALID_CHAP_ALGORITHM )
126 #define EINFO_EPROTO_INVALID_CHAP_ALGORITHM \
127 __einfo_uniqify ( EINFO_EPROTO, 0x01, "Invalid CHAP algorithm" )
128 #define EPROTO_INVALID_CHAP_IDENTIFIER \
129 __einfo_error ( EINFO_EPROTO_INVALID_CHAP_IDENTIFIER )
130 #define EINFO_EPROTO_INVALID_CHAP_IDENTIFIER \
131 __einfo_uniqify ( EINFO_EPROTO, 0x02, "Invalid CHAP identifier" )
132 #define EPROTO_INVALID_LARGE_BINARY \
133 __einfo_error ( EINFO_EPROTO_INVALID_LARGE_BINARY )
134 #define EINFO_EPROTO_INVALID_LARGE_BINARY \
135 __einfo_uniqify ( EINFO_EPROTO, 0x03, "Invalid large binary value" )
136 #define EPROTO_INVALID_CHAP_RESPONSE \
137 __einfo_error ( EINFO_EPROTO_INVALID_CHAP_RESPONSE )
138 #define EINFO_EPROTO_INVALID_CHAP_RESPONSE \
139 __einfo_uniqify ( EINFO_EPROTO, 0x04, "Invalid CHAP response" )
140 #define EPROTO_INVALID_KEY_VALUE_PAIR \
141 __einfo_error ( EINFO_EPROTO_INVALID_KEY_VALUE_PAIR )
142 #define EINFO_EPROTO_INVALID_KEY_VALUE_PAIR \
143 __einfo_uniqify ( EINFO_EPROTO, 0x05, "Invalid key/value pair" )
144 #define EPROTO_VALUE_REJECTED \
145 __einfo_error ( EINFO_EPROTO_VALUE_REJECTED )
146 #define EINFO_EPROTO_VALUE_REJECTED \
147 __einfo_uniqify ( EINFO_EPROTO, 0x06, "Parameter rejected" )
149 static void iscsi_start_tx ( struct iscsi_session
*iscsi
);
150 static void iscsi_start_login ( struct iscsi_session
*iscsi
);
151 static void iscsi_start_data_out ( struct iscsi_session
*iscsi
,
152 unsigned int datasn
);
155 * Finish receiving PDU data into buffer
157 * @v iscsi iSCSI session
159 static void iscsi_rx_buffered_data_done ( struct iscsi_session
*iscsi
) {
160 free ( iscsi
->rx_buffer
);
161 iscsi
->rx_buffer
= NULL
;
165 * Receive PDU data into buffer
167 * @v iscsi iSCSI session
168 * @v data Data to receive
169 * @v len Length of data
170 * @ret rc Return status code
172 * This can be used when the RX PDU type handler wishes to buffer up
173 * all received data and process the PDU as a single unit. The caller
174 * is repsonsible for calling iscsi_rx_buffered_data_done() after
175 * processing the data.
177 static int iscsi_rx_buffered_data ( struct iscsi_session
*iscsi
,
178 const void *data
, size_t len
) {
180 /* Allocate buffer on first call */
181 if ( ! iscsi
->rx_buffer
) {
182 iscsi
->rx_buffer
= malloc ( iscsi
->rx_len
);
183 if ( ! iscsi
->rx_buffer
)
187 /* Copy data to buffer */
188 assert ( ( iscsi
->rx_offset
+ len
) <= iscsi
->rx_len
);
189 memcpy ( ( iscsi
->rx_buffer
+ iscsi
->rx_offset
), data
, len
);
197 * @v refcnt Reference counter
199 static void iscsi_free ( struct refcnt
*refcnt
) {
200 struct iscsi_session
*iscsi
=
201 container_of ( refcnt
, struct iscsi_session
, refcnt
);
203 free ( iscsi
->initiator_iqn
);
204 free ( iscsi
->target_address
);
205 free ( iscsi
->target_iqn
);
206 free ( iscsi
->initiator_username
);
207 free ( iscsi
->initiator_password
);
208 free ( iscsi
->target_username
);
209 free ( iscsi
->target_password
);
210 chap_finish ( &iscsi
->chap
);
211 iscsi_rx_buffered_data_done ( iscsi
);
212 free ( iscsi
->command
);
217 * Shut down iSCSI interface
219 * @v iscsi iSCSI session
220 * @v rc Reason for close
222 static void iscsi_close ( struct iscsi_session
*iscsi
, int rc
) {
224 /* A TCP graceful close is still an error from our point of view */
228 DBGC ( iscsi
, "iSCSI %p closed: %s\n", iscsi
, strerror ( rc
) );
230 /* Stop transmission process */
231 process_del ( &iscsi
->process
);
233 /* Shut down interfaces */
234 intf_shutdown ( &iscsi
->socket
, rc
);
235 intf_shutdown ( &iscsi
->control
, rc
);
236 intf_shutdown ( &iscsi
->data
, rc
);
240 * Assign new iSCSI initiator task tag
242 * @v iscsi iSCSI session
244 static void iscsi_new_itt ( struct iscsi_session
*iscsi
) {
245 static uint16_t itt_idx
;
247 iscsi
->itt
= ( ISCSI_TAG_MAGIC
| (++itt_idx
) );
251 * Open iSCSI transport-layer connection
253 * @v iscsi iSCSI session
254 * @ret rc Return status code
256 static int iscsi_open_connection ( struct iscsi_session
*iscsi
) {
257 struct sockaddr_tcpip target
;
260 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
261 assert ( iscsi
->rx_state
== ISCSI_RX_BHS
);
262 assert ( iscsi
->rx_offset
== 0 );
265 memset ( &target
, 0, sizeof ( target
) );
266 target
.st_port
= htons ( iscsi
->target_port
);
267 if ( ( rc
= xfer_open_named_socket ( &iscsi
->socket
, SOCK_STREAM
,
268 ( struct sockaddr
* ) &target
,
269 iscsi
->target_address
,
271 DBGC ( iscsi
, "iSCSI %p could not open socket: %s\n",
272 iscsi
, strerror ( rc
) );
276 /* Enter security negotiation phase */
277 iscsi
->status
= ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE
|
278 ISCSI_STATUS_STRINGS_SECURITY
);
279 if ( iscsi
->target_username
)
280 iscsi
->status
|= ISCSI_STATUS_AUTH_REVERSE_REQUIRED
;
282 /* Assign new ISID */
283 iscsi
->isid_iana_qual
= ( random() & 0xffff );
285 /* Assign fresh initiator task tag */
286 iscsi_new_itt ( iscsi
);
289 iscsi_start_login ( iscsi
);
295 * Close iSCSI transport-layer connection
297 * @v iscsi iSCSI session
298 * @v rc Reason for close
300 * Closes the transport-layer connection and resets the session state
301 * ready to attempt a fresh login.
303 static void iscsi_close_connection ( struct iscsi_session
*iscsi
, int rc
) {
305 /* Close all data transfer interfaces */
306 intf_restart ( &iscsi
->socket
, rc
);
308 /* Clear connection status */
311 /* Reset TX and RX state machines */
312 iscsi
->tx_state
= ISCSI_TX_IDLE
;
313 iscsi
->rx_state
= ISCSI_RX_BHS
;
314 iscsi
->rx_offset
= 0;
316 /* Free any temporary dynamically allocated memory */
317 chap_finish ( &iscsi
->chap
);
318 iscsi_rx_buffered_data_done ( iscsi
);
322 * Mark iSCSI SCSI operation as complete
324 * @v iscsi iSCSI session
325 * @v rc Return status code
326 * @v rsp SCSI response, if any
328 * Note that iscsi_scsi_done() will not close the connection, and must
329 * therefore be called only when the internal state machines are in an
330 * appropriate state, otherwise bad things may happen on the next call
331 * to iscsi_scsi_command(). The general rule is to call
332 * iscsi_scsi_done() only at the end of receiving a PDU; at this point
333 * the TX and RX engines should both be idle.
335 static void iscsi_scsi_done ( struct iscsi_session
*iscsi
, int rc
,
336 struct scsi_rsp
*rsp
) {
337 uint32_t itt
= iscsi
->itt
;
339 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
342 free ( iscsi
->command
);
343 iscsi
->command
= NULL
;
345 /* Send SCSI response, if any */
347 scsi_response ( &iscsi
->data
, rsp
);
349 /* Close SCSI command, if this is still the same command. (It
350 * is possible that the command interface has already been
351 * closed as a result of the SCSI response we sent.)
353 if ( iscsi
->itt
== itt
)
354 intf_restart ( &iscsi
->data
, rc
);
357 /****************************************************************************
359 * iSCSI SCSI command issuing
364 * Build iSCSI SCSI command BHS
366 * @v iscsi iSCSI session
368 * We don't currently support bidirectional commands (i.e. with both
369 * Data-In and Data-Out segments); these would require providing code
370 * to generate an AHS, and there doesn't seem to be any need for it at
373 static void iscsi_start_command ( struct iscsi_session
*iscsi
) {
374 struct iscsi_bhs_scsi_command
*command
= &iscsi
->tx_bhs
.scsi_command
;
376 assert ( ! ( iscsi
->command
->data_in
&& iscsi
->command
->data_out
) );
378 /* Construct BHS and initiate transmission */
379 iscsi_start_tx ( iscsi
);
380 command
->opcode
= ISCSI_OPCODE_SCSI_COMMAND
;
381 command
->flags
= ( ISCSI_FLAG_FINAL
|
382 ISCSI_COMMAND_ATTR_SIMPLE
);
383 if ( iscsi
->command
->data_in
)
384 command
->flags
|= ISCSI_COMMAND_FLAG_READ
;
385 if ( iscsi
->command
->data_out
)
386 command
->flags
|= ISCSI_COMMAND_FLAG_WRITE
;
387 /* lengths left as zero */
388 memcpy ( &command
->lun
, &iscsi
->command
->lun
,
389 sizeof ( command
->lun
) );
390 command
->itt
= htonl ( iscsi
->itt
);
391 command
->exp_len
= htonl ( iscsi
->command
->data_in_len
|
392 iscsi
->command
->data_out_len
);
393 command
->cmdsn
= htonl ( iscsi
->cmdsn
);
394 command
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
395 memcpy ( &command
->cdb
, &iscsi
->command
->cdb
, sizeof ( command
->cdb
));
396 DBGC2 ( iscsi
, "iSCSI %p start " SCSI_CDB_FORMAT
" %s %#zx\n",
397 iscsi
, SCSI_CDB_DATA ( command
->cdb
),
398 ( iscsi
->command
->data_in ?
"in" : "out" ),
399 ( iscsi
->command
->data_in ?
400 iscsi
->command
->data_in_len
:
401 iscsi
->command
->data_out_len
) );
405 * Receive data segment of an iSCSI SCSI response PDU
407 * @v iscsi iSCSI session
408 * @v data Received data
409 * @v len Length of received data
410 * @v remaining Data remaining after this data
411 * @ret rc Return status code
413 static int iscsi_rx_scsi_response ( struct iscsi_session
*iscsi
,
414 const void *data
, size_t len
,
416 struct iscsi_bhs_scsi_response
*response
417 = &iscsi
->rx_bhs
.scsi_response
;
419 uint32_t residual_count
;
423 /* Buffer up the PDU data */
424 if ( ( rc
= iscsi_rx_buffered_data ( iscsi
, data
, len
) ) != 0 ) {
425 DBGC ( iscsi
, "iSCSI %p could not buffer SCSI response: %s\n",
426 iscsi
, strerror ( rc
) );
432 /* Parse SCSI response and discard buffer */
433 memset ( &rsp
, 0, sizeof ( rsp
) );
434 rsp
.status
= response
->status
;
435 residual_count
= ntohl ( response
->residual_count
);
436 if ( response
->flags
& ISCSI_DATA_FLAG_OVERFLOW
) {
437 rsp
.overrun
= residual_count
;
438 } else if ( response
->flags
& ISCSI_DATA_FLAG_UNDERFLOW
) {
439 rsp
.overrun
= -(residual_count
);
441 data_len
= ISCSI_DATA_LEN ( response
->lengths
);
443 scsi_parse_sense ( ( iscsi
->rx_buffer
+ 2 ), ( data_len
- 2 ),
446 iscsi_rx_buffered_data_done ( iscsi
);
448 /* Check for errors */
449 if ( response
->response
!= ISCSI_RESPONSE_COMMAND_COMPLETE
)
452 /* Mark as completed */
453 iscsi_scsi_done ( iscsi
, 0, &rsp
);
458 * Receive data segment of an iSCSI data-in PDU
460 * @v iscsi iSCSI session
461 * @v data Received data
462 * @v len Length of received data
463 * @v remaining Data remaining after this data
464 * @ret rc Return status code
466 static int iscsi_rx_data_in ( struct iscsi_session
*iscsi
,
467 const void *data
, size_t len
,
469 struct iscsi_bhs_data_in
*data_in
= &iscsi
->rx_bhs
.data_in
;
470 unsigned long offset
;
472 /* Copy data to data-in buffer */
473 offset
= ntohl ( data_in
->offset
) + iscsi
->rx_offset
;
474 assert ( iscsi
->command
!= NULL
);
475 assert ( iscsi
->command
->data_in
);
476 assert ( ( offset
+ len
) <= iscsi
->command
->data_in_len
);
477 copy_to_user ( iscsi
->command
->data_in
, offset
, data
, len
);
479 /* Wait for whole SCSI response to arrive */
483 /* Mark as completed if status is present */
484 if ( data_in
->flags
& ISCSI_DATA_FLAG_STATUS
) {
485 assert ( ( offset
+ len
) == iscsi
->command
->data_in_len
);
486 assert ( data_in
->flags
& ISCSI_FLAG_FINAL
);
487 /* iSCSI cannot return an error status via a data-in */
488 iscsi_scsi_done ( iscsi
, 0, NULL
);
495 * Receive data segment of an iSCSI R2T PDU
497 * @v iscsi iSCSI session
498 * @v data Received data
499 * @v len Length of received data
500 * @v remaining Data remaining after this data
501 * @ret rc Return status code
503 static int iscsi_rx_r2t ( struct iscsi_session
*iscsi
,
504 const void *data __unused
, size_t len __unused
,
505 size_t remaining __unused
) {
506 struct iscsi_bhs_r2t
*r2t
= &iscsi
->rx_bhs
.r2t
;
508 /* Record transfer parameters and trigger first data-out */
509 iscsi
->ttt
= ntohl ( r2t
->ttt
);
510 iscsi
->transfer_offset
= ntohl ( r2t
->offset
);
511 iscsi
->transfer_len
= ntohl ( r2t
->len
);
512 iscsi_start_data_out ( iscsi
, 0 );
518 * Build iSCSI data-out BHS
520 * @v iscsi iSCSI session
521 * @v datasn Data sequence number within the transfer
524 static void iscsi_start_data_out ( struct iscsi_session
*iscsi
,
525 unsigned int datasn
) {
526 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
527 unsigned long offset
;
528 unsigned long remaining
;
531 /* We always send 512-byte Data-Out PDUs; this removes the
532 * need to worry about the target's MaxRecvDataSegmentLength.
534 offset
= datasn
* 512;
535 remaining
= iscsi
->transfer_len
- offset
;
540 /* Construct BHS and initiate transmission */
541 iscsi_start_tx ( iscsi
);
542 data_out
->opcode
= ISCSI_OPCODE_DATA_OUT
;
543 if ( len
== remaining
)
544 data_out
->flags
= ( ISCSI_FLAG_FINAL
);
545 ISCSI_SET_LENGTHS ( data_out
->lengths
, 0, len
);
546 data_out
->lun
= iscsi
->command
->lun
;
547 data_out
->itt
= htonl ( iscsi
->itt
);
548 data_out
->ttt
= htonl ( iscsi
->ttt
);
549 data_out
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
550 data_out
->datasn
= htonl ( datasn
);
551 data_out
->offset
= htonl ( iscsi
->transfer_offset
+ offset
);
552 DBGC ( iscsi
, "iSCSI %p start data out DataSN %#x len %#lx\n",
553 iscsi
, datasn
, len
);
557 * Complete iSCSI data-out PDU transmission
559 * @v iscsi iSCSI session
562 static void iscsi_data_out_done ( struct iscsi_session
*iscsi
) {
563 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
565 /* If we haven't reached the end of the sequence, start
566 * sending the next data-out PDU.
568 if ( ! ( data_out
->flags
& ISCSI_FLAG_FINAL
) )
569 iscsi_start_data_out ( iscsi
, ntohl ( data_out
->datasn
) + 1 );
573 * Send iSCSI data-out data segment
575 * @v iscsi iSCSI session
576 * @ret rc Return status code
578 static int iscsi_tx_data_out ( struct iscsi_session
*iscsi
) {
579 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
580 struct io_buffer
*iobuf
;
581 unsigned long offset
;
585 offset
= ntohl ( data_out
->offset
);
586 len
= ISCSI_DATA_LEN ( data_out
->lengths
);
587 pad_len
= ISCSI_DATA_PAD_LEN ( data_out
->lengths
);
589 assert ( iscsi
->command
!= NULL
);
590 assert ( iscsi
->command
->data_out
);
591 assert ( ( offset
+ len
) <= iscsi
->command
->data_out_len
);
593 iobuf
= xfer_alloc_iob ( &iscsi
->socket
, ( len
+ pad_len
) );
597 copy_from_user ( iob_put ( iobuf
, len
),
598 iscsi
->command
->data_out
, offset
, len
);
599 memset ( iob_put ( iobuf
, pad_len
), 0, pad_len
);
601 return xfer_deliver_iob ( &iscsi
->socket
, iobuf
);
605 * Receive data segment of an iSCSI NOP-In
607 * @v iscsi iSCSI session
608 * @v data Received data
609 * @v len Length of received data
610 * @v remaining Data remaining after this data
611 * @ret rc Return status code
613 static int iscsi_rx_nop_in ( struct iscsi_session
*iscsi
,
614 const void *data __unused
, size_t len __unused
,
615 size_t remaining __unused
) {
616 struct iscsi_nop_in
*nop_in
= &iscsi
->rx_bhs
.nop_in
;
618 DBGC2 ( iscsi
, "iSCSI %p received NOP-In\n", iscsi
);
620 /* We don't currently have the ability to respond to NOP-Ins
621 * sent as ping requests, but we can happily accept NOP-Ins
622 * sent merely to update CmdSN.
624 if ( nop_in
->ttt
!= htonl ( ISCSI_TAG_RESERVED
) ) {
625 DBGC ( iscsi
, "iSCSI %p received unsupported NOP-In with TTT "
626 "%08x\n", iscsi
, ntohl ( nop_in
->ttt
) );
627 return -ENOTSUP_NOP_IN
;
633 /****************************************************************************
640 * Build iSCSI login request strings
642 * @v iscsi iSCSI session
644 * These are the initial set of strings sent in the first login
645 * request PDU. We want the following settings:
649 * MaxConnections is irrelevant; we make only one connection anyway [4]
651 * ImmediateData is irrelevant; we never send immediate data [4]
652 * MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
653 * MaxBurstLength=262144 (default; we don't care) [3]
654 * FirstBurstLength=262144 (default; we don't care)
655 * DefaultTime2Wait=0 [2]
656 * DefaultTime2Retain=0 [2]
657 * MaxOutstandingR2T=1
659 * DataSequenceInOrder=Yes
660 * ErrorRecoveryLevel=0
662 * [1] InitialR2T has an OR resolution function, so the target may
663 * force us to use it. We therefore simplify our logic by always
666 * [2] These ensure that we can safely start a new task once we have
667 * reconnected after a failure, without having to manually tidy up
670 * [3] We are quite happy to use the RFC-defined default values for
671 * these parameters, but some targets (notably OpenSolaris)
672 * incorrectly assume a default value of zero, so we explicitly
673 * specify the default values.
675 * [4] We are quite happy to use the RFC-defined default values for
676 * these parameters, but some targets (notably a QNAP TS-639Pro) fail
677 * unless they are supplied, so we explicitly specify the default
680 static int iscsi_build_login_request_strings ( struct iscsi_session
*iscsi
,
681 void *data
, size_t len
) {
682 unsigned int used
= 0;
683 const char *auth_method
;
685 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_SECURITY
) {
686 /* Default to allowing no authentication */
687 auth_method
= "None";
688 /* If we have a credential to supply, permit CHAP */
689 if ( iscsi
->initiator_username
)
690 auth_method
= "CHAP,None";
691 /* If we have a credential to check, force CHAP */
692 if ( iscsi
->target_username
)
693 auth_method
= "CHAP";
694 used
+= ssnprintf ( data
+ used
, len
- used
,
697 "SessionType=Normal%c"
699 iscsi
->initiator_iqn
, 0,
700 iscsi
->target_iqn
, 0, 0,
704 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_ALGORITHM
) {
705 used
+= ssnprintf ( data
+ used
, len
- used
, "CHAP_A=5%c", 0 );
708 if ( ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_RESPONSE
) ) {
709 char buf
[ base16_encoded_len ( iscsi
->chap
.response_len
) + 1 ];
710 assert ( iscsi
->initiator_username
!= NULL
);
711 base16_encode ( iscsi
->chap
.response
, iscsi
->chap
.response_len
,
712 buf
, sizeof ( buf
) );
713 used
+= ssnprintf ( data
+ used
, len
- used
,
714 "CHAP_N=%s%cCHAP_R=0x%s%c",
715 iscsi
->initiator_username
, 0, buf
, 0 );
718 if ( ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_CHALLENGE
) ) {
719 size_t challenge_len
= ( sizeof ( iscsi
->chap_challenge
) - 1 );
720 char buf
[ base16_encoded_len ( challenge_len
) + 1 ];
721 base16_encode ( ( iscsi
->chap_challenge
+ 1 ), challenge_len
,
722 buf
, sizeof ( buf
) );
723 used
+= ssnprintf ( data
+ used
, len
- used
,
724 "CHAP_I=%d%cCHAP_C=0x%s%c",
725 iscsi
->chap_challenge
[0], 0, buf
, 0 );
728 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_OPERATIONAL
) {
729 used
+= ssnprintf ( data
+ used
, len
- used
,
730 "HeaderDigest=None%c"
735 "MaxRecvDataSegmentLength=8192%c"
736 "MaxBurstLength=262144%c"
737 "DefaultTime2Wait=0%c"
738 "DefaultTime2Retain=0%c"
739 "MaxOutstandingR2T=1%c"
740 "DataPDUInOrder=Yes%c"
741 "DataSequenceInOrder=Yes%c"
742 "ErrorRecoveryLevel=0%c",
743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
750 * Build iSCSI login request BHS
752 * @v iscsi iSCSI session
754 static void iscsi_start_login ( struct iscsi_session
*iscsi
) {
755 struct iscsi_bhs_login_request
*request
= &iscsi
->tx_bhs
.login_request
;
758 switch ( iscsi
->status
& ISCSI_LOGIN_CSG_MASK
) {
759 case ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION
:
760 DBGC ( iscsi
, "iSCSI %p entering security negotiation\n",
763 case ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION
:
764 DBGC ( iscsi
, "iSCSI %p entering operational negotiation\n",
771 /* Construct BHS and initiate transmission */
772 iscsi_start_tx ( iscsi
);
773 request
->opcode
= ( ISCSI_OPCODE_LOGIN_REQUEST
|
774 ISCSI_FLAG_IMMEDIATE
);
775 request
->flags
= ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) |
776 ISCSI_LOGIN_FLAG_TRANSITION
);
777 /* version_max and version_min left as zero */
778 len
= iscsi_build_login_request_strings ( iscsi
, NULL
, 0 );
779 ISCSI_SET_LENGTHS ( request
->lengths
, 0, len
);
780 request
->isid_iana_en
= htonl ( ISCSI_ISID_IANA
|
781 IANA_EN_FEN_SYSTEMS
);
782 request
->isid_iana_qual
= htons ( iscsi
->isid_iana_qual
);
783 /* tsih left as zero */
784 request
->itt
= htonl ( iscsi
->itt
);
785 /* cid left as zero */
786 request
->cmdsn
= htonl ( iscsi
->cmdsn
);
787 request
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
791 * Complete iSCSI login request PDU transmission
793 * @v iscsi iSCSI session
796 static void iscsi_login_request_done ( struct iscsi_session
*iscsi
) {
798 /* Clear any "strings to send" flags */
799 iscsi
->status
&= ~ISCSI_STATUS_STRINGS_MASK
;
801 /* Free any dynamically allocated storage used for login */
802 chap_finish ( &iscsi
->chap
);
806 * Transmit data segment of an iSCSI login request PDU
808 * @v iscsi iSCSI session
809 * @ret rc Return status code
811 * For login requests, the data segment consists of the login strings.
813 static int iscsi_tx_login_request ( struct iscsi_session
*iscsi
) {
814 struct iscsi_bhs_login_request
*request
= &iscsi
->tx_bhs
.login_request
;
815 struct io_buffer
*iobuf
;
819 len
= ISCSI_DATA_LEN ( request
->lengths
);
820 pad_len
= ISCSI_DATA_PAD_LEN ( request
->lengths
);
821 iobuf
= xfer_alloc_iob ( &iscsi
->socket
, ( len
+ pad_len
) );
824 iob_put ( iobuf
, len
);
825 iscsi_build_login_request_strings ( iscsi
, iobuf
->data
, len
);
826 memset ( iob_put ( iobuf
, pad_len
), 0, pad_len
);
828 return xfer_deliver_iob ( &iscsi
->socket
, iobuf
);
832 * Decode large binary value
834 * @v encoded Encoded large binary value
836 * @v len Length of data buffer
837 * @ret len Length of raw data, or negative error
839 static int iscsi_large_binary_decode ( const char *encoded
, uint8_t *raw
,
842 /* Check for initial '0x' or '0b' and decode as appropriate */
843 if ( *(encoded
++) == '0' ) {
844 switch ( tolower ( *(encoded
++) ) ) {
846 return base16_decode ( encoded
, raw
, len
);
848 return base64_decode ( encoded
, raw
, len
);
852 return -EPROTO_INVALID_LARGE_BINARY
;
856 * Handle iSCSI TargetAddress text value
858 * @v iscsi iSCSI session
859 * @v value TargetAddress value
860 * @ret rc Return status code
862 static int iscsi_handle_targetaddress_value ( struct iscsi_session
*iscsi
,
863 const char *value
) {
866 DBGC ( iscsi
, "iSCSI %p will redirect to %s\n", iscsi
, value
);
868 /* Replace target address */
869 free ( iscsi
->target_address
);
870 iscsi
->target_address
= strdup ( value
);
871 if ( ! iscsi
->target_address
)
874 /* Replace target port */
875 iscsi
->target_port
= htons ( ISCSI_PORT
);
876 separator
= strchr ( iscsi
->target_address
, ':' );
879 iscsi
->target_port
= strtoul ( ( separator
+ 1 ), NULL
, 0 );
886 * Handle iSCSI AuthMethod text value
888 * @v iscsi iSCSI session
889 * @v value AuthMethod value
890 * @ret rc Return status code
892 static int iscsi_handle_authmethod_value ( struct iscsi_session
*iscsi
,
893 const char *value
) {
895 /* If server requests CHAP, send the CHAP_A string */
896 if ( strcmp ( value
, "CHAP" ) == 0 ) {
897 DBGC ( iscsi
, "iSCSI %p initiating CHAP authentication\n",
899 iscsi
->status
|= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM
|
900 ISCSI_STATUS_AUTH_FORWARD_REQUIRED
);
907 * Handle iSCSI CHAP_A text value
909 * @v iscsi iSCSI session
910 * @v value CHAP_A value
911 * @ret rc Return status code
913 static int iscsi_handle_chap_a_value ( struct iscsi_session
*iscsi
,
914 const char *value
) {
916 /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
917 * the server responds with anything else it is a protocol
920 if ( strcmp ( value
, "5" ) != 0 ) {
921 DBGC ( iscsi
, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
923 return -EPROTO_INVALID_CHAP_ALGORITHM
;
930 * Handle iSCSI CHAP_I text value
932 * @v iscsi iSCSI session
933 * @v value CHAP_I value
934 * @ret rc Return status code
936 static int iscsi_handle_chap_i_value ( struct iscsi_session
*iscsi
,
937 const char *value
) {
938 unsigned int identifier
;
942 /* The CHAP identifier is an integer value */
943 identifier
= strtoul ( value
, &endp
, 0 );
944 if ( *endp
!= '\0' ) {
945 DBGC ( iscsi
, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
947 return -EPROTO_INVALID_CHAP_IDENTIFIER
;
950 /* Prepare for CHAP with MD5 */
951 chap_finish ( &iscsi
->chap
);
952 if ( ( rc
= chap_init ( &iscsi
->chap
, &md5_algorithm
) ) != 0 ) {
953 DBGC ( iscsi
, "iSCSI %p could not initialise CHAP: %s\n",
954 iscsi
, strerror ( rc
) );
958 /* Identifier and secret are the first two components of the
961 chap_set_identifier ( &iscsi
->chap
, identifier
);
962 if ( iscsi
->initiator_password
) {
963 chap_update ( &iscsi
->chap
, iscsi
->initiator_password
,
964 strlen ( iscsi
->initiator_password
) );
971 * Handle iSCSI CHAP_C text value
973 * @v iscsi iSCSI session
974 * @v value CHAP_C value
975 * @ret rc Return status code
977 static int iscsi_handle_chap_c_value ( struct iscsi_session
*iscsi
,
978 const char *value
) {
979 uint8_t buf
[ strlen ( value
) ]; /* Decoding never expands data */
984 /* Process challenge */
985 len
= iscsi_large_binary_decode ( value
, buf
, sizeof ( buf
) );
988 DBGC ( iscsi
, "iSCSI %p invalid CHAP challenge \"%s\": %s\n",
989 iscsi
, value
, strerror ( rc
) );
992 chap_update ( &iscsi
->chap
, buf
, len
);
994 /* Build CHAP response */
995 DBGC ( iscsi
, "iSCSI %p sending CHAP response\n", iscsi
);
996 chap_respond ( &iscsi
->chap
);
997 iscsi
->status
|= ISCSI_STATUS_STRINGS_CHAP_RESPONSE
;
999 /* Send CHAP challenge, if applicable */
1000 if ( iscsi
->target_username
) {
1001 iscsi
->status
|= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE
;
1002 /* Generate CHAP challenge data */
1003 for ( i
= 0 ; i
< sizeof ( iscsi
->chap_challenge
) ; i
++ ) {
1004 iscsi
->chap_challenge
[i
] = random();
1012 * Handle iSCSI CHAP_N text value
1014 * @v iscsi iSCSI session
1015 * @v value CHAP_N value
1016 * @ret rc Return status code
1018 static int iscsi_handle_chap_n_value ( struct iscsi_session
*iscsi
,
1019 const char *value
) {
1021 /* The target username isn't actually involved at any point in
1022 * the authentication process; it merely serves to identify
1023 * which password the target is using to generate the CHAP
1024 * response. We unnecessarily verify that the username is as
1025 * expected, in order to provide mildly helpful diagnostics if
1026 * the target is supplying the wrong username/password
1029 if ( iscsi
->target_username
&&
1030 ( strcmp ( iscsi
->target_username
, value
) != 0 ) ) {
1031 DBGC ( iscsi
, "iSCSI %p target username \"%s\" incorrect "
1032 "(wanted \"%s\")\n",
1033 iscsi
, value
, iscsi
->target_username
);
1034 return -EACCES_INCORRECT_TARGET_USERNAME
;
1041 * Handle iSCSI CHAP_R text value
1043 * @v iscsi iSCSI session
1044 * @v value CHAP_R value
1045 * @ret rc Return status code
1047 static int iscsi_handle_chap_r_value ( struct iscsi_session
*iscsi
,
1048 const char *value
) {
1049 uint8_t buf
[ strlen ( value
) ]; /* Decoding never expands data */
1053 /* Generate CHAP response for verification */
1054 chap_finish ( &iscsi
->chap
);
1055 if ( ( rc
= chap_init ( &iscsi
->chap
, &md5_algorithm
) ) != 0 ) {
1056 DBGC ( iscsi
, "iSCSI %p could not initialise CHAP: %s\n",
1057 iscsi
, strerror ( rc
) );
1060 chap_set_identifier ( &iscsi
->chap
, iscsi
->chap_challenge
[0] );
1061 if ( iscsi
->target_password
) {
1062 chap_update ( &iscsi
->chap
, iscsi
->target_password
,
1063 strlen ( iscsi
->target_password
) );
1065 chap_update ( &iscsi
->chap
, &iscsi
->chap_challenge
[1],
1066 ( sizeof ( iscsi
->chap_challenge
) - 1 ) );
1067 chap_respond ( &iscsi
->chap
);
1069 /* Process response */
1070 len
= iscsi_large_binary_decode ( value
, buf
, sizeof ( buf
) );
1073 DBGC ( iscsi
, "iSCSI %p invalid CHAP response \"%s\": %s\n",
1074 iscsi
, value
, strerror ( rc
) );
1078 /* Check CHAP response */
1079 if ( len
!= ( int ) iscsi
->chap
.response_len
) {
1080 DBGC ( iscsi
, "iSCSI %p invalid CHAP response length\n",
1082 return -EPROTO_INVALID_CHAP_RESPONSE
;
1084 if ( memcmp ( buf
, iscsi
->chap
.response
, len
) != 0 ) {
1085 DBGC ( iscsi
, "iSCSI %p incorrect CHAP response \"%s\"\n",
1087 return -EACCES_INCORRECT_TARGET_PASSWORD
;
1090 /* Mark session as authenticated */
1091 iscsi
->status
|= ISCSI_STATUS_AUTH_REVERSE_OK
;
1096 /** An iSCSI text string that we want to handle */
1097 struct iscsi_string_type
{
1100 * This is the portion preceding the "=" sign,
1101 * e.g. "InitiatorName", "CHAP_A", etc.
1104 /** Handle iSCSI string value
1106 * @v iscsi iSCSI session
1107 * @v value iSCSI string value
1108 * @ret rc Return status code
1110 int ( * handle
) ( struct iscsi_session
*iscsi
, const char *value
);
1113 /** iSCSI text strings that we want to handle */
1114 static struct iscsi_string_type iscsi_string_types
[] = {
1115 { "TargetAddress", iscsi_handle_targetaddress_value
},
1116 { "AuthMethod", iscsi_handle_authmethod_value
},
1117 { "CHAP_A", iscsi_handle_chap_a_value
},
1118 { "CHAP_I", iscsi_handle_chap_i_value
},
1119 { "CHAP_C", iscsi_handle_chap_c_value
},
1120 { "CHAP_N", iscsi_handle_chap_n_value
},
1121 { "CHAP_R", iscsi_handle_chap_r_value
},
1126 * Handle iSCSI string
1128 * @v iscsi iSCSI session
1129 * @v string iSCSI string (in "key=value" format)
1130 * @ret rc Return status code
1132 static int iscsi_handle_string ( struct iscsi_session
*iscsi
,
1133 const char *string
) {
1134 struct iscsi_string_type
*type
;
1135 const char *separator
;
1140 /* Find separator */
1141 separator
= strchr ( string
, '=' );
1142 if ( ! separator
) {
1143 DBGC ( iscsi
, "iSCSI %p malformed string %s\n",
1145 return -EPROTO_INVALID_KEY_VALUE_PAIR
;
1147 key_len
= ( separator
- string
);
1148 value
= ( separator
+ 1 );
1150 /* Check for rejections. Since we send only non-rejectable
1151 * values, any rejection is a fatal protocol error.
1153 if ( strcmp ( value
, "Reject" ) == 0 ) {
1154 DBGC ( iscsi
, "iSCSI %p rejection: %s\n", iscsi
, string
);
1155 return -EPROTO_VALUE_REJECTED
;
1158 /* Handle key/value pair */
1159 for ( type
= iscsi_string_types
; type
->key
; type
++ ) {
1160 if ( strncmp ( string
, type
->key
, key_len
) != 0 )
1162 DBGC ( iscsi
, "iSCSI %p handling %s\n", iscsi
, string
);
1163 if ( ( rc
= type
->handle ( iscsi
, value
) ) != 0 ) {
1164 DBGC ( iscsi
, "iSCSI %p could not handle %s: %s\n",
1165 iscsi
, string
, strerror ( rc
) );
1170 DBGC ( iscsi
, "iSCSI %p ignoring %s\n", iscsi
, string
);
1175 * Handle iSCSI strings
1177 * @v iscsi iSCSI session
1178 * @v string iSCSI string buffer
1179 * @v len Length of string buffer
1180 * @ret rc Return status code
1182 static int iscsi_handle_strings ( struct iscsi_session
*iscsi
,
1183 const char *strings
, size_t len
) {
1187 /* Handle each string in turn, taking care not to overrun the
1188 * data buffer in case of badly-terminated data.
1191 string_len
= ( strnlen ( strings
, len
) + 1 );
1192 if ( string_len
> len
)
1194 if ( ( rc
= iscsi_handle_string ( iscsi
, strings
) ) != 0 )
1196 strings
+= string_len
;
1203 * Convert iSCSI response status to return status code
1205 * @v status_class iSCSI status class
1206 * @v status_detail iSCSI status detail
1207 * @ret rc Return status code
1209 static int iscsi_status_to_rc ( unsigned int status_class
,
1210 unsigned int status_detail
) {
1211 switch ( status_class
) {
1212 case ISCSI_STATUS_INITIATOR_ERROR
:
1213 switch ( status_detail
) {
1214 case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION
:
1215 return -EPERM_INITIATOR_AUTHENTICATION
;
1216 case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION
:
1217 return -EPERM_INITIATOR_AUTHORISATION
;
1218 case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND
:
1219 case ISCSI_STATUS_INITIATOR_ERROR_REMOVED
:
1222 return -ENOTSUP_INITIATOR_STATUS
;
1224 case ISCSI_STATUS_TARGET_ERROR
:
1225 switch ( status_detail
) {
1226 case ISCSI_STATUS_TARGET_ERROR_UNAVAILABLE
:
1227 return -EIO_TARGET_UNAVAILABLE
;
1228 case ISCSI_STATUS_TARGET_ERROR_NO_RESOURCES
:
1229 return -EIO_TARGET_NO_RESOURCES
;
1231 return -ENOTSUP_TARGET_STATUS
;
1239 * Receive data segment of an iSCSI login response PDU
1241 * @v iscsi iSCSI session
1242 * @v data Received data
1243 * @v len Length of received data
1244 * @v remaining Data remaining after this data
1245 * @ret rc Return status code
1247 static int iscsi_rx_login_response ( struct iscsi_session
*iscsi
,
1248 const void *data
, size_t len
,
1249 size_t remaining
) {
1250 struct iscsi_bhs_login_response
*response
1251 = &iscsi
->rx_bhs
.login_response
;
1254 /* Buffer up the PDU data */
1255 if ( ( rc
= iscsi_rx_buffered_data ( iscsi
, data
, len
) ) != 0 ) {
1256 DBGC ( iscsi
, "iSCSI %p could not buffer login response: %s\n",
1257 iscsi
, strerror ( rc
) );
1263 /* Process string data and discard string buffer */
1264 if ( ( rc
= iscsi_handle_strings ( iscsi
, iscsi
->rx_buffer
,
1265 iscsi
->rx_len
) ) != 0 )
1267 iscsi_rx_buffered_data_done ( iscsi
);
1269 /* Check for login redirection */
1270 if ( response
->status_class
== ISCSI_STATUS_REDIRECT
) {
1271 DBGC ( iscsi
, "iSCSI %p redirecting to new server\n", iscsi
);
1272 iscsi_close_connection ( iscsi
, 0 );
1273 if ( ( rc
= iscsi_open_connection ( iscsi
) ) != 0 ) {
1274 DBGC ( iscsi
, "iSCSI %p could not redirect: %s\n ",
1275 iscsi
, strerror ( rc
) );
1281 /* Check for fatal errors */
1282 if ( response
->status_class
!= 0 ) {
1283 DBGC ( iscsi
, "iSCSI login failure: class %02x detail %02x\n",
1284 response
->status_class
, response
->status_detail
);
1285 rc
= iscsi_status_to_rc ( response
->status_class
,
1286 response
->status_detail
);
1290 /* Handle login transitions */
1291 if ( response
->flags
& ISCSI_LOGIN_FLAG_TRANSITION
) {
1292 iscsi
->status
&= ~( ISCSI_STATUS_PHASE_MASK
|
1293 ISCSI_STATUS_STRINGS_MASK
);
1294 switch ( response
->flags
& ISCSI_LOGIN_NSG_MASK
) {
1295 case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION
:
1297 ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE
|
1298 ISCSI_STATUS_STRINGS_OPERATIONAL
);
1300 case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE
:
1301 iscsi
->status
|= ISCSI_STATUS_FULL_FEATURE_PHASE
;
1304 DBGC ( iscsi
, "iSCSI %p got invalid response flags "
1305 "%02x\n", iscsi
, response
->flags
);
1310 /* Send next login request PDU if we haven't reached the full
1311 * feature phase yet.
1313 if ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) !=
1314 ISCSI_STATUS_FULL_FEATURE_PHASE
) {
1315 iscsi_start_login ( iscsi
);
1319 /* Check that target authentication was successful (if required) */
1320 if ( ( iscsi
->status
& ISCSI_STATUS_AUTH_REVERSE_REQUIRED
) &&
1321 ! ( iscsi
->status
& ISCSI_STATUS_AUTH_REVERSE_OK
) ) {
1322 DBGC ( iscsi
, "iSCSI %p nefarious target tried to bypass "
1323 "authentication\n", iscsi
);
1327 /* Notify SCSI layer of window change */
1328 DBGC ( iscsi
, "iSCSI %p entering full feature phase\n", iscsi
);
1329 xfer_window_changed ( &iscsi
->control
);
1334 /****************************************************************************
1336 * iSCSI to socket interface
1343 * @v iscsi iSCSI session
1345 static void iscsi_tx_pause ( struct iscsi_session
*iscsi
) {
1346 process_del ( &iscsi
->process
);
1352 * @v iscsi iSCSI session
1354 static void iscsi_tx_resume ( struct iscsi_session
*iscsi
) {
1355 process_add ( &iscsi
->process
);
1359 * Start up a new TX PDU
1361 * @v iscsi iSCSI session
1363 * This initiates the process of sending a new PDU. Only one PDU may
1364 * be in transit at any one time.
1366 static void iscsi_start_tx ( struct iscsi_session
*iscsi
) {
1368 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
1370 /* Initialise TX BHS */
1371 memset ( &iscsi
->tx_bhs
, 0, sizeof ( iscsi
->tx_bhs
) );
1373 /* Flag TX engine to start transmitting */
1374 iscsi
->tx_state
= ISCSI_TX_BHS
;
1376 /* Start transmission process */
1377 iscsi_tx_resume ( iscsi
);
1383 * @v iscsi iSCSI session
1384 * @ret rc Return status code
1386 static int iscsi_tx_nothing ( struct iscsi_session
*iscsi __unused
) {
1391 * Transmit basic header segment of an iSCSI PDU
1393 * @v iscsi iSCSI session
1394 * @ret rc Return status code
1396 static int iscsi_tx_bhs ( struct iscsi_session
*iscsi
) {
1397 return xfer_deliver_raw ( &iscsi
->socket
, &iscsi
->tx_bhs
,
1398 sizeof ( iscsi
->tx_bhs
) );
1402 * Transmit data segment of an iSCSI PDU
1404 * @v iscsi iSCSI session
1405 * @ret rc Return status code
1407 * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
1408 * will be valid when this is called.
1410 static int iscsi_tx_data ( struct iscsi_session
*iscsi
) {
1411 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1413 switch ( common
->opcode
& ISCSI_OPCODE_MASK
) {
1414 case ISCSI_OPCODE_DATA_OUT
:
1415 return iscsi_tx_data_out ( iscsi
);
1416 case ISCSI_OPCODE_LOGIN_REQUEST
:
1417 return iscsi_tx_login_request ( iscsi
);
1419 /* Nothing to send in other states */
1425 * Complete iSCSI PDU transmission
1427 * @v iscsi iSCSI session
1429 * Called when a PDU has been completely transmitted and the TX state
1430 * machine is about to enter the idle state. iscsi::tx_bhs will be
1431 * valid for the just-completed PDU when this is called.
1433 static void iscsi_tx_done ( struct iscsi_session
*iscsi
) {
1434 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1436 /* Stop transmission process */
1437 iscsi_tx_pause ( iscsi
);
1439 switch ( common
->opcode
& ISCSI_OPCODE_MASK
) {
1440 case ISCSI_OPCODE_DATA_OUT
:
1441 iscsi_data_out_done ( iscsi
);
1443 case ISCSI_OPCODE_LOGIN_REQUEST
:
1444 iscsi_login_request_done ( iscsi
);
1453 * Transmit iSCSI PDU
1455 * @v iscsi iSCSI session
1456 * @v buf Temporary data buffer
1457 * @v len Length of temporary data buffer
1459 * Constructs data to be sent for the current TX state
1461 static void iscsi_tx_step ( struct iscsi_session
*iscsi
) {
1462 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1463 int ( * tx
) ( struct iscsi_session
*iscsi
);
1464 enum iscsi_tx_state next_state
;
1468 /* Select fragment to transmit */
1470 switch ( iscsi
->tx_state
) {
1473 tx_len
= sizeof ( iscsi
->tx_bhs
);
1474 next_state
= ISCSI_TX_AHS
;
1477 tx
= iscsi_tx_nothing
;
1479 next_state
= ISCSI_TX_DATA
;
1483 tx_len
= ISCSI_DATA_LEN ( common
->lengths
);
1484 next_state
= ISCSI_TX_IDLE
;
1487 /* Nothing to do; pause processing */
1488 iscsi_tx_pause ( iscsi
);
1495 /* Check for window availability, if needed */
1496 if ( tx_len
&& ( xfer_window ( &iscsi
->socket
) == 0 ) ) {
1497 /* Cannot transmit at this point; pause
1498 * processing and wait for window to reopen
1500 iscsi_tx_pause ( iscsi
);
1505 if ( ( rc
= tx ( iscsi
) ) != 0 ) {
1506 DBGC ( iscsi
, "iSCSI %p could not transmit: %s\n",
1507 iscsi
, strerror ( rc
) );
1508 /* Transmission errors are fatal */
1509 iscsi_close ( iscsi
, rc
);
1513 /* Move to next state */
1514 iscsi
->tx_state
= next_state
;
1516 /* If we have moved to the idle state, mark
1517 * transmission as complete
1519 if ( iscsi
->tx_state
== ISCSI_TX_IDLE
)
1520 iscsi_tx_done ( iscsi
);
1524 /** iSCSI TX process descriptor */
1525 static struct process_descriptor iscsi_process_desc
=
1526 PROC_DESC ( struct iscsi_session
, process
, iscsi_tx_step
);
1529 * Receive basic header segment of an iSCSI PDU
1531 * @v iscsi iSCSI session
1532 * @v data Received data
1533 * @v len Length of received data
1534 * @v remaining Data remaining after this data
1535 * @ret rc Return status code
1537 * This fills in iscsi::rx_bhs with the data from the BHS portion of
1540 static int iscsi_rx_bhs ( struct iscsi_session
*iscsi
, const void *data
,
1541 size_t len
, size_t remaining __unused
) {
1542 memcpy ( &iscsi
->rx_bhs
.bytes
[iscsi
->rx_offset
], data
, len
);
1543 if ( ( iscsi
->rx_offset
+ len
) >= sizeof ( iscsi
->rx_bhs
) ) {
1544 DBGC2 ( iscsi
, "iSCSI %p received PDU opcode %#x len %#x\n",
1545 iscsi
, iscsi
->rx_bhs
.common
.opcode
,
1546 ISCSI_DATA_LEN ( iscsi
->rx_bhs
.common
.lengths
) );
1552 * Discard portion of an iSCSI PDU.
1554 * @v iscsi iSCSI session
1555 * @v data Received data
1556 * @v len Length of received data
1557 * @v remaining Data remaining after this data
1558 * @ret rc Return status code
1560 * This discards data from a portion of a received PDU.
1562 static int iscsi_rx_discard ( struct iscsi_session
*iscsi __unused
,
1563 const void *data __unused
, size_t len __unused
,
1564 size_t remaining __unused
) {
1570 * Receive data segment of an iSCSI PDU
1572 * @v iscsi iSCSI session
1573 * @v data Received data
1574 * @v len Length of received data
1575 * @v remaining Data remaining after this data
1576 * @ret rc Return status code
1578 * Handle processing of part of a PDU data segment. iscsi::rx_bhs
1579 * will be valid when this is called.
1581 static int iscsi_rx_data ( struct iscsi_session
*iscsi
, const void *data
,
1582 size_t len
, size_t remaining
) {
1583 struct iscsi_bhs_common_response
*response
1584 = &iscsi
->rx_bhs
.common_response
;
1586 /* Update cmdsn and statsn */
1587 iscsi
->cmdsn
= ntohl ( response
->expcmdsn
);
1588 iscsi
->statsn
= ntohl ( response
->statsn
);
1590 switch ( response
->opcode
& ISCSI_OPCODE_MASK
) {
1591 case ISCSI_OPCODE_LOGIN_RESPONSE
:
1592 return iscsi_rx_login_response ( iscsi
, data
, len
, remaining
);
1593 case ISCSI_OPCODE_SCSI_RESPONSE
:
1594 return iscsi_rx_scsi_response ( iscsi
, data
, len
, remaining
);
1595 case ISCSI_OPCODE_DATA_IN
:
1596 return iscsi_rx_data_in ( iscsi
, data
, len
, remaining
);
1597 case ISCSI_OPCODE_R2T
:
1598 return iscsi_rx_r2t ( iscsi
, data
, len
, remaining
);
1599 case ISCSI_OPCODE_NOP_IN
:
1600 return iscsi_rx_nop_in ( iscsi
, data
, len
, remaining
);
1604 DBGC ( iscsi
, "iSCSI %p unknown opcode %02x\n", iscsi
,
1606 return -ENOTSUP_OPCODE
;
1613 * @v iscsi iSCSI session
1614 * @v iobuf I/O buffer
1615 * @v meta Data transfer metadata
1616 * @ret rc Return status code
1618 * This handles received PDUs. The receive strategy is to fill in
1619 * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
1620 * throw away any AHS portion, and then process each part of the data
1621 * portion as it arrives. The data processing routine therefore
1622 * always has a full copy of the BHS available, even for portions of
1623 * the data in different packets to the BHS.
1625 static int iscsi_socket_deliver ( struct iscsi_session
*iscsi
,
1626 struct io_buffer
*iobuf
,
1627 struct xfer_metadata
*meta __unused
) {
1628 struct iscsi_bhs_common
*common
= &iscsi
->rx_bhs
.common
;
1629 int ( * rx
) ( struct iscsi_session
*iscsi
, const void *data
,
1630 size_t len
, size_t remaining
);
1631 enum iscsi_rx_state next_state
;
1637 switch ( iscsi
->rx_state
) {
1640 iscsi
->rx_len
= sizeof ( iscsi
->rx_bhs
);
1641 next_state
= ISCSI_RX_AHS
;
1644 rx
= iscsi_rx_discard
;
1645 iscsi
->rx_len
= 4 * ISCSI_AHS_LEN ( common
->lengths
);
1646 next_state
= ISCSI_RX_DATA
;
1650 iscsi
->rx_len
= ISCSI_DATA_LEN ( common
->lengths
);
1651 next_state
= ISCSI_RX_DATA_PADDING
;
1653 case ISCSI_RX_DATA_PADDING
:
1654 rx
= iscsi_rx_discard
;
1655 iscsi
->rx_len
= ISCSI_DATA_PAD_LEN ( common
->lengths
);
1656 next_state
= ISCSI_RX_BHS
;
1664 frag_len
= iscsi
->rx_len
- iscsi
->rx_offset
;
1665 if ( frag_len
> iob_len ( iobuf
) )
1666 frag_len
= iob_len ( iobuf
);
1667 remaining
= iscsi
->rx_len
- iscsi
->rx_offset
- frag_len
;
1668 if ( ( rc
= rx ( iscsi
, iobuf
->data
, frag_len
,
1669 remaining
) ) != 0 ) {
1670 DBGC ( iscsi
, "iSCSI %p could not process received "
1671 "data: %s\n", iscsi
, strerror ( rc
) );
1675 iscsi
->rx_offset
+= frag_len
;
1676 iob_pull ( iobuf
, frag_len
);
1678 /* If all the data for this state has not yet been
1679 * received, stay in this state for now.
1681 if ( iscsi
->rx_offset
!= iscsi
->rx_len
) {
1686 iscsi
->rx_state
= next_state
;
1687 iscsi
->rx_offset
= 0;
1691 /* Free I/O buffer */
1694 /* Destroy session on error */
1696 iscsi_close ( iscsi
, rc
);
1702 * Handle redirection event
1704 * @v iscsi iSCSI session
1705 * @v type Location type
1706 * @v args Remaining arguments depend upon location type
1707 * @ret rc Return status code
1709 static int iscsi_vredirect ( struct iscsi_session
*iscsi
, int type
,
1712 struct sockaddr
*peer
;
1715 /* Intercept redirects to a LOCATION_SOCKET and record the IP
1716 * address for the iBFT. This is a bit of a hack, but avoids
1717 * inventing an ioctl()-style call to retrieve the socket
1718 * address from a data-xfer interface.
1720 if ( type
== LOCATION_SOCKET
) {
1721 va_copy ( tmp
, args
);
1722 ( void ) va_arg ( tmp
, int ); /* Discard "semantics" */
1723 peer
= va_arg ( tmp
, struct sockaddr
* );
1724 memcpy ( &iscsi
->target_sockaddr
, peer
,
1725 sizeof ( iscsi
->target_sockaddr
) );
1729 /* Redirect to new location */
1730 if ( ( rc
= xfer_vreopen ( &iscsi
->socket
, type
, args
) ) != 0 )
1736 iscsi_close ( iscsi
, rc
);
1740 /** iSCSI socket interface operations */
1741 static struct interface_operation iscsi_socket_operations
[] = {
1742 INTF_OP ( xfer_deliver
, struct iscsi_session
*, iscsi_socket_deliver
),
1743 INTF_OP ( xfer_window_changed
, struct iscsi_session
*,
1745 INTF_OP ( xfer_vredirect
, struct iscsi_session
*, iscsi_vredirect
),
1746 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_close
),
1749 /** iSCSI socket interface descriptor */
1750 static struct interface_descriptor iscsi_socket_desc
=
1751 INTF_DESC ( struct iscsi_session
, socket
, iscsi_socket_operations
);
1753 /****************************************************************************
1755 * iSCSI command issuing
1760 * Check iSCSI flow-control window
1762 * @v iscsi iSCSI session
1763 * @ret len Length of window
1765 static size_t iscsi_scsi_window ( struct iscsi_session
*iscsi
) {
1767 if ( ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) ==
1768 ISCSI_STATUS_FULL_FEATURE_PHASE
) &&
1769 ( iscsi
->command
== NULL
) ) {
1770 /* We cannot handle concurrent commands */
1778 * Issue iSCSI SCSI command
1780 * @v iscsi iSCSI session
1781 * @v parent Parent interface
1782 * @v command SCSI command
1783 * @ret tag Command tag, or negative error
1785 static int iscsi_scsi_command ( struct iscsi_session
*iscsi
,
1786 struct interface
*parent
,
1787 struct scsi_cmd
*command
) {
1789 /* This iSCSI implementation cannot handle multiple concurrent
1790 * commands or commands arriving before login is complete.
1792 if ( iscsi_scsi_window ( iscsi
) == 0 ) {
1793 DBGC ( iscsi
, "iSCSI %p cannot handle concurrent commands\n",
1799 iscsi
->command
= malloc ( sizeof ( *command
) );
1800 if ( ! iscsi
->command
)
1802 memcpy ( iscsi
->command
, command
, sizeof ( *command
) );
1804 /* Assign new ITT */
1805 iscsi_new_itt ( iscsi
);
1807 /* Start sending command */
1808 iscsi_start_command ( iscsi
);
1810 /* Attach to parent interface and return */
1811 intf_plug_plug ( &iscsi
->data
, parent
);
1815 /** iSCSI SCSI command-issuing interface operations */
1816 static struct interface_operation iscsi_control_op
[] = {
1817 INTF_OP ( scsi_command
, struct iscsi_session
*, iscsi_scsi_command
),
1818 INTF_OP ( xfer_window
, struct iscsi_session
*, iscsi_scsi_window
),
1819 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_close
),
1820 INTF_OP ( acpi_describe
, struct iscsi_session
*, ibft_describe
),
1823 /** iSCSI SCSI command-issuing interface descriptor */
1824 static struct interface_descriptor iscsi_control_desc
=
1825 INTF_DESC ( struct iscsi_session
, control
, iscsi_control_op
);
1828 * Close iSCSI command
1830 * @v iscsi iSCSI session
1831 * @v rc Reason for close
1833 static void iscsi_command_close ( struct iscsi_session
*iscsi
, int rc
) {
1835 /* Restart interface */
1836 intf_restart ( &iscsi
->data
, rc
);
1838 /* Treat unsolicited command closures mid-command as fatal,
1839 * because we have no code to handle partially-completed PDUs.
1841 if ( iscsi
->command
!= NULL
)
1842 iscsi_close ( iscsi
, ( ( rc
== 0 ) ?
-ECANCELED
: rc
) );
1845 /** iSCSI SCSI command interface operations */
1846 static struct interface_operation iscsi_data_op
[] = {
1847 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_command_close
),
1850 /** iSCSI SCSI command interface descriptor */
1851 static struct interface_descriptor iscsi_data_desc
=
1852 INTF_DESC ( struct iscsi_session
, data
, iscsi_data_op
);
1854 /****************************************************************************
1860 /** iSCSI root path components (as per RFC4173) */
1861 enum iscsi_root_path_component
{
1870 /** iSCSI initiator IQN setting */
1871 const struct setting initiator_iqn_setting
__setting ( SETTING_SANBOOT_EXTRA
,
1873 .name
= "initiator-iqn",
1874 .description
= "iSCSI initiator name",
1875 .tag
= DHCP_ISCSI_INITIATOR_IQN
,
1876 .type
= &setting_type_string
,
1879 /** iSCSI reverse username setting */
1880 const struct setting reverse_username_setting
__setting ( SETTING_AUTH_EXTRA
,
1881 reverse
-username
) = {
1882 .name
= "reverse-username",
1883 .description
= "Reverse user name",
1884 .tag
= DHCP_EB_REVERSE_USERNAME
,
1885 .type
= &setting_type_string
,
1888 /** iSCSI reverse password setting */
1889 const struct setting reverse_password_setting
__setting ( SETTING_AUTH_EXTRA
,
1890 reverse
-password
) = {
1891 .name
= "reverse-password",
1892 .description
= "Reverse password",
1893 .tag
= DHCP_EB_REVERSE_PASSWORD
,
1894 .type
= &setting_type_string
,
1898 * Parse iSCSI root path
1900 * @v iscsi iSCSI session
1901 * @v root_path iSCSI root path (as per RFC4173)
1902 * @ret rc Return status code
1904 static int iscsi_parse_root_path ( struct iscsi_session
*iscsi
,
1905 const char *root_path
) {
1906 char rp_copy
[ strlen ( root_path
) + 1 ];
1907 char *rp_comp
[NUM_RP_COMPONENTS
];
1912 /* Split root path into component parts */
1913 strcpy ( rp_copy
, root_path
);
1916 if ( i
== NUM_RP_COMPONENTS
)
1918 for ( ; *rp
!= ':' ; rp
++ ) {
1920 DBGC ( iscsi
, "iSCSI %p root path \"%s\" "
1921 "too short\n", iscsi
, root_path
);
1922 return -EINVAL_ROOT_PATH_TOO_SHORT
;
1928 /* Use root path components to configure iSCSI session */
1929 iscsi
->target_address
= strdup ( rp_comp
[RP_SERVERNAME
] );
1930 if ( ! iscsi
->target_address
)
1932 iscsi
->target_port
= strtoul ( rp_comp
[RP_PORT
], NULL
, 10 );
1933 if ( ! iscsi
->target_port
)
1934 iscsi
->target_port
= ISCSI_PORT
;
1935 if ( ( rc
= scsi_parse_lun ( rp_comp
[RP_LUN
], &iscsi
->lun
) ) != 0 ) {
1936 DBGC ( iscsi
, "iSCSI %p invalid LUN \"%s\"\n",
1937 iscsi
, rp_comp
[RP_LUN
] );
1940 iscsi
->target_iqn
= strdup ( rp_comp
[RP_TARGETNAME
] );
1941 if ( ! iscsi
->target_iqn
)
1948 * Fetch iSCSI settings
1950 * @v iscsi iSCSI session
1951 * @ret rc Return status code
1953 static int iscsi_fetch_settings ( struct iscsi_session
*iscsi
) {
1958 /* Fetch relevant settings. Don't worry about freeing on
1959 * error, since iscsi_free() will take care of that anyway.
1961 fetch_string_setting_copy ( NULL
, &username_setting
,
1962 &iscsi
->initiator_username
);
1963 fetch_string_setting_copy ( NULL
, &password_setting
,
1964 &iscsi
->initiator_password
);
1965 fetch_string_setting_copy ( NULL
, &reverse_username_setting
,
1966 &iscsi
->target_username
);
1967 fetch_string_setting_copy ( NULL
, &reverse_password_setting
,
1968 &iscsi
->target_password
);
1970 /* Use explicit initiator IQN if provided */
1971 fetch_string_setting_copy ( NULL
, &initiator_iqn_setting
,
1972 &iscsi
->initiator_iqn
);
1973 if ( iscsi
->initiator_iqn
)
1976 /* Otherwise, try to construct an initiator IQN from the hostname */
1977 fetch_string_setting_copy ( NULL
, &hostname_setting
, &hostname
);
1979 len
= asprintf ( &iscsi
->initiator_iqn
,
1980 ISCSI_DEFAULT_IQN_PREFIX
":%s", hostname
);
1983 DBGC ( iscsi
, "iSCSI %p could not allocate initiator "
1987 assert ( iscsi
->initiator_iqn
);
1991 /* Otherwise, try to construct an initiator IQN from the UUID */
1992 if ( ( len
= fetch_uuid_setting ( NULL
, &uuid_setting
, &uuid
) ) < 0 ) {
1993 DBGC ( iscsi
, "iSCSI %p has no suitable initiator IQN\n",
1995 return -EINVAL_NO_INITIATOR_IQN
;
1997 if ( ( len
= asprintf ( &iscsi
->initiator_iqn
,
1998 ISCSI_DEFAULT_IQN_PREFIX
":%s",
1999 uuid_ntoa ( &uuid
) ) ) < 0 ) {
2000 DBGC ( iscsi
, "iSCSI %p could not allocate initiator IQN\n",
2004 assert ( iscsi
->initiator_iqn
);
2011 * Check iSCSI authentication details
2013 * @v iscsi iSCSI session
2014 * @ret rc Return status code
2016 static int iscsi_check_auth ( struct iscsi_session
*iscsi
) {
2018 /* Check for invalid authentication combinations */
2019 if ( ( /* Initiator username without password (or vice-versa) */
2020 ( !! iscsi
->initiator_username
) ^
2021 ( !! iscsi
->initiator_password
) ) ||
2022 ( /* Target username without password (or vice-versa) */
2023 ( !! iscsi
->target_username
) ^
2024 ( !! iscsi
->target_password
) ) ||
2025 ( /* Target (reverse) without initiator (forward) */
2026 ( iscsi
->target_username
&&
2027 ( ! iscsi
->initiator_username
) ) ) ) {
2028 DBGC ( iscsi
, "iSCSI %p invalid credentials: initiator "
2029 "%sname,%spw, target %sname,%spw\n", iscsi
,
2030 ( iscsi
->initiator_username ?
"" : "no " ),
2031 ( iscsi
->initiator_password ?
"" : "no " ),
2032 ( iscsi
->target_username ?
"" : "no " ),
2033 ( iscsi
->target_password ?
"" : "no " ) );
2034 return -EINVAL_BAD_CREDENTIAL_MIX
;
2043 * @v parent Parent interface
2045 * @ret rc Return status code
2047 static int iscsi_open ( struct interface
*parent
, struct uri
*uri
) {
2048 struct iscsi_session
*iscsi
;
2052 if ( ! uri
->opaque
) {
2053 rc
= -EINVAL_NO_ROOT_PATH
;
2054 goto err_sanity_uri
;
2057 /* Allocate and initialise structure */
2058 iscsi
= zalloc ( sizeof ( *iscsi
) );
2063 ref_init ( &iscsi
->refcnt
, iscsi_free
);
2064 intf_init ( &iscsi
->control
, &iscsi_control_desc
, &iscsi
->refcnt
);
2065 intf_init ( &iscsi
->data
, &iscsi_data_desc
, &iscsi
->refcnt
);
2066 intf_init ( &iscsi
->socket
, &iscsi_socket_desc
, &iscsi
->refcnt
);
2067 process_init_stopped ( &iscsi
->process
, &iscsi_process_desc
,
2070 /* Parse root path */
2071 if ( ( rc
= iscsi_parse_root_path ( iscsi
, uri
->opaque
) ) != 0 )
2072 goto err_parse_root_path
;
2073 /* Set fields not specified by root path */
2074 if ( ( rc
= iscsi_fetch_settings ( iscsi
) ) != 0 )
2075 goto err_fetch_settings
;
2076 /* Validate authentication */
2077 if ( ( rc
= iscsi_check_auth ( iscsi
) ) != 0 )
2078 goto err_check_auth
;
2081 if ( ! iscsi
->target_address
) {
2082 DBGC ( iscsi
, "iSCSI %p does not yet support discovery\n",
2084 rc
= -ENOTSUP_DISCOVERY
;
2085 goto err_sanity_address
;
2087 if ( ! iscsi
->target_iqn
) {
2088 DBGC ( iscsi
, "iSCSI %p no target address supplied in %s\n",
2089 iscsi
, uri
->opaque
);
2090 rc
= -EINVAL_NO_TARGET_IQN
;
2091 goto err_sanity_iqn
;
2093 DBGC ( iscsi
, "iSCSI %p initiator %s\n",iscsi
, iscsi
->initiator_iqn
);
2094 DBGC ( iscsi
, "iSCSI %p target %s %s\n",
2095 iscsi
, iscsi
->target_address
, iscsi
->target_iqn
);
2098 if ( ( rc
= iscsi_open_connection ( iscsi
) ) != 0 )
2099 goto err_open_connection
;
2101 /* Attach SCSI device to parent interface */
2102 if ( ( rc
= scsi_open ( parent
, &iscsi
->control
,
2103 &iscsi
->lun
) ) != 0 ) {
2104 DBGC ( iscsi
, "iSCSI %p could not create SCSI device: %s\n",
2105 iscsi
, strerror ( rc
) );
2109 /* Mortalise self, and return */
2110 ref_put ( &iscsi
->refcnt
);
2114 err_open_connection
:
2119 err_parse_root_path
:
2120 iscsi_close ( iscsi
, rc
);
2121 ref_put ( &iscsi
->refcnt
);
2127 /** iSCSI URI opener */
2128 struct uri_opener iscsi_uri_opener __uri_opener
= {