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_nullify ( &iscsi
->data
); /* avoid potential loops */
235 intf_shutdown ( &iscsi
->socket
, rc
);
236 intf_shutdown ( &iscsi
->control
, rc
);
237 intf_shutdown ( &iscsi
->data
, rc
);
241 * Assign new iSCSI initiator task tag
243 * @v iscsi iSCSI session
245 static void iscsi_new_itt ( struct iscsi_session
*iscsi
) {
246 static uint16_t itt_idx
;
248 iscsi
->itt
= ( ISCSI_TAG_MAGIC
| (++itt_idx
) );
252 * Open iSCSI transport-layer connection
254 * @v iscsi iSCSI session
255 * @ret rc Return status code
257 static int iscsi_open_connection ( struct iscsi_session
*iscsi
) {
258 struct sockaddr_tcpip target
;
261 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
262 assert ( iscsi
->rx_state
== ISCSI_RX_BHS
);
263 assert ( iscsi
->rx_offset
== 0 );
266 memset ( &target
, 0, sizeof ( target
) );
267 target
.st_port
= htons ( iscsi
->target_port
);
268 if ( ( rc
= xfer_open_named_socket ( &iscsi
->socket
, SOCK_STREAM
,
269 ( struct sockaddr
* ) &target
,
270 iscsi
->target_address
,
272 DBGC ( iscsi
, "iSCSI %p could not open socket: %s\n",
273 iscsi
, strerror ( rc
) );
277 /* Enter security negotiation phase */
278 iscsi
->status
= ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE
|
279 ISCSI_STATUS_STRINGS_SECURITY
);
280 if ( iscsi
->target_username
)
281 iscsi
->status
|= ISCSI_STATUS_AUTH_REVERSE_REQUIRED
;
283 /* Assign new ISID */
284 iscsi
->isid_iana_qual
= ( random() & 0xffff );
286 /* Assign fresh initiator task tag */
287 iscsi_new_itt ( iscsi
);
290 iscsi_start_login ( iscsi
);
296 * Close iSCSI transport-layer connection
298 * @v iscsi iSCSI session
299 * @v rc Reason for close
301 * Closes the transport-layer connection and resets the session state
302 * ready to attempt a fresh login.
304 static void iscsi_close_connection ( struct iscsi_session
*iscsi
, int rc
) {
306 /* Close all data transfer interfaces */
307 intf_restart ( &iscsi
->socket
, rc
);
309 /* Clear connection status */
312 /* Reset TX and RX state machines */
313 iscsi
->tx_state
= ISCSI_TX_IDLE
;
314 iscsi
->rx_state
= ISCSI_RX_BHS
;
315 iscsi
->rx_offset
= 0;
317 /* Free any temporary dynamically allocated memory */
318 chap_finish ( &iscsi
->chap
);
319 iscsi_rx_buffered_data_done ( iscsi
);
323 * Mark iSCSI SCSI operation as complete
325 * @v iscsi iSCSI session
326 * @v rc Return status code
327 * @v rsp SCSI response, if any
329 * Note that iscsi_scsi_done() will not close the connection, and must
330 * therefore be called only when the internal state machines are in an
331 * appropriate state, otherwise bad things may happen on the next call
332 * to iscsi_scsi_command(). The general rule is to call
333 * iscsi_scsi_done() only at the end of receiving a PDU; at this point
334 * the TX and RX engines should both be idle.
336 static void iscsi_scsi_done ( struct iscsi_session
*iscsi
, int rc
,
337 struct scsi_rsp
*rsp
) {
338 uint32_t itt
= iscsi
->itt
;
340 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
343 free ( iscsi
->command
);
344 iscsi
->command
= NULL
;
346 /* Send SCSI response, if any */
348 scsi_response ( &iscsi
->data
, rsp
);
350 /* Close SCSI command, if this is still the same command. (It
351 * is possible that the command interface has already been
352 * closed as a result of the SCSI response we sent.)
354 if ( iscsi
->itt
== itt
)
355 intf_restart ( &iscsi
->data
, rc
);
358 /****************************************************************************
360 * iSCSI SCSI command issuing
365 * Build iSCSI SCSI command BHS
367 * @v iscsi iSCSI session
369 * We don't currently support bidirectional commands (i.e. with both
370 * Data-In and Data-Out segments); these would require providing code
371 * to generate an AHS, and there doesn't seem to be any need for it at
374 static void iscsi_start_command ( struct iscsi_session
*iscsi
) {
375 struct iscsi_bhs_scsi_command
*command
= &iscsi
->tx_bhs
.scsi_command
;
377 assert ( ! ( iscsi
->command
->data_in
&& iscsi
->command
->data_out
) );
379 /* Construct BHS and initiate transmission */
380 iscsi_start_tx ( iscsi
);
381 command
->opcode
= ISCSI_OPCODE_SCSI_COMMAND
;
382 command
->flags
= ( ISCSI_FLAG_FINAL
|
383 ISCSI_COMMAND_ATTR_SIMPLE
);
384 if ( iscsi
->command
->data_in
)
385 command
->flags
|= ISCSI_COMMAND_FLAG_READ
;
386 if ( iscsi
->command
->data_out
)
387 command
->flags
|= ISCSI_COMMAND_FLAG_WRITE
;
388 /* lengths left as zero */
389 memcpy ( &command
->lun
, &iscsi
->command
->lun
,
390 sizeof ( command
->lun
) );
391 command
->itt
= htonl ( iscsi
->itt
);
392 command
->exp_len
= htonl ( iscsi
->command
->data_in_len
|
393 iscsi
->command
->data_out_len
);
394 command
->cmdsn
= htonl ( iscsi
->cmdsn
);
395 command
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
396 memcpy ( &command
->cdb
, &iscsi
->command
->cdb
, sizeof ( command
->cdb
));
397 DBGC2 ( iscsi
, "iSCSI %p start " SCSI_CDB_FORMAT
" %s %#zx\n",
398 iscsi
, SCSI_CDB_DATA ( command
->cdb
),
399 ( iscsi
->command
->data_in ?
"in" : "out" ),
400 ( iscsi
->command
->data_in ?
401 iscsi
->command
->data_in_len
:
402 iscsi
->command
->data_out_len
) );
406 * Receive data segment of an iSCSI SCSI response PDU
408 * @v iscsi iSCSI session
409 * @v data Received data
410 * @v len Length of received data
411 * @v remaining Data remaining after this data
412 * @ret rc Return status code
414 static int iscsi_rx_scsi_response ( struct iscsi_session
*iscsi
,
415 const void *data
, size_t len
,
417 struct iscsi_bhs_scsi_response
*response
418 = &iscsi
->rx_bhs
.scsi_response
;
420 uint32_t residual_count
;
424 /* Buffer up the PDU data */
425 if ( ( rc
= iscsi_rx_buffered_data ( iscsi
, data
, len
) ) != 0 ) {
426 DBGC ( iscsi
, "iSCSI %p could not buffer SCSI response: %s\n",
427 iscsi
, strerror ( rc
) );
433 /* Parse SCSI response and discard buffer */
434 memset ( &rsp
, 0, sizeof ( rsp
) );
435 rsp
.status
= response
->status
;
436 residual_count
= ntohl ( response
->residual_count
);
437 if ( response
->flags
& ISCSI_DATA_FLAG_OVERFLOW
) {
438 rsp
.overrun
= residual_count
;
439 } else if ( response
->flags
& ISCSI_DATA_FLAG_UNDERFLOW
) {
440 rsp
.overrun
= -(residual_count
);
442 data_len
= ISCSI_DATA_LEN ( response
->lengths
);
444 scsi_parse_sense ( ( iscsi
->rx_buffer
+ 2 ), ( data_len
- 2 ),
447 iscsi_rx_buffered_data_done ( iscsi
);
449 /* Check for errors */
450 if ( response
->response
!= ISCSI_RESPONSE_COMMAND_COMPLETE
)
453 /* Mark as completed */
454 iscsi_scsi_done ( iscsi
, 0, &rsp
);
459 * Receive data segment of an iSCSI data-in PDU
461 * @v iscsi iSCSI session
462 * @v data Received data
463 * @v len Length of received data
464 * @v remaining Data remaining after this data
465 * @ret rc Return status code
467 static int iscsi_rx_data_in ( struct iscsi_session
*iscsi
,
468 const void *data
, size_t len
,
470 struct iscsi_bhs_data_in
*data_in
= &iscsi
->rx_bhs
.data_in
;
471 unsigned long offset
;
473 /* Copy data to data-in buffer */
474 offset
= ntohl ( data_in
->offset
) + iscsi
->rx_offset
;
475 assert ( iscsi
->command
!= NULL
);
476 assert ( iscsi
->command
->data_in
);
477 assert ( ( offset
+ len
) <= iscsi
->command
->data_in_len
);
478 copy_to_user ( iscsi
->command
->data_in
, offset
, data
, len
);
480 /* Wait for whole SCSI response to arrive */
484 /* Mark as completed if status is present */
485 if ( data_in
->flags
& ISCSI_DATA_FLAG_STATUS
) {
486 assert ( ( offset
+ len
) == iscsi
->command
->data_in_len
);
487 assert ( data_in
->flags
& ISCSI_FLAG_FINAL
);
488 /* iSCSI cannot return an error status via a data-in */
489 iscsi_scsi_done ( iscsi
, 0, NULL
);
496 * Receive data segment of an iSCSI R2T PDU
498 * @v iscsi iSCSI session
499 * @v data Received data
500 * @v len Length of received data
501 * @v remaining Data remaining after this data
502 * @ret rc Return status code
504 static int iscsi_rx_r2t ( struct iscsi_session
*iscsi
,
505 const void *data __unused
, size_t len __unused
,
506 size_t remaining __unused
) {
507 struct iscsi_bhs_r2t
*r2t
= &iscsi
->rx_bhs
.r2t
;
509 /* Record transfer parameters and trigger first data-out */
510 iscsi
->ttt
= ntohl ( r2t
->ttt
);
511 iscsi
->transfer_offset
= ntohl ( r2t
->offset
);
512 iscsi
->transfer_len
= ntohl ( r2t
->len
);
513 iscsi_start_data_out ( iscsi
, 0 );
519 * Build iSCSI data-out BHS
521 * @v iscsi iSCSI session
522 * @v datasn Data sequence number within the transfer
525 static void iscsi_start_data_out ( struct iscsi_session
*iscsi
,
526 unsigned int datasn
) {
527 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
528 unsigned long offset
;
529 unsigned long remaining
;
532 /* We always send 512-byte Data-Out PDUs; this removes the
533 * need to worry about the target's MaxRecvDataSegmentLength.
535 offset
= datasn
* 512;
536 remaining
= iscsi
->transfer_len
- offset
;
541 /* Construct BHS and initiate transmission */
542 iscsi_start_tx ( iscsi
);
543 data_out
->opcode
= ISCSI_OPCODE_DATA_OUT
;
544 if ( len
== remaining
)
545 data_out
->flags
= ( ISCSI_FLAG_FINAL
);
546 ISCSI_SET_LENGTHS ( data_out
->lengths
, 0, len
);
547 data_out
->lun
= iscsi
->command
->lun
;
548 data_out
->itt
= htonl ( iscsi
->itt
);
549 data_out
->ttt
= htonl ( iscsi
->ttt
);
550 data_out
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
551 data_out
->datasn
= htonl ( datasn
);
552 data_out
->offset
= htonl ( iscsi
->transfer_offset
+ offset
);
553 DBGC ( iscsi
, "iSCSI %p start data out DataSN %#x len %#lx\n",
554 iscsi
, datasn
, len
);
558 * Complete iSCSI data-out PDU transmission
560 * @v iscsi iSCSI session
563 static void iscsi_data_out_done ( struct iscsi_session
*iscsi
) {
564 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
566 /* If we haven't reached the end of the sequence, start
567 * sending the next data-out PDU.
569 if ( ! ( data_out
->flags
& ISCSI_FLAG_FINAL
) )
570 iscsi_start_data_out ( iscsi
, ntohl ( data_out
->datasn
) + 1 );
574 * Send iSCSI data-out data segment
576 * @v iscsi iSCSI session
577 * @ret rc Return status code
579 static int iscsi_tx_data_out ( struct iscsi_session
*iscsi
) {
580 struct iscsi_bhs_data_out
*data_out
= &iscsi
->tx_bhs
.data_out
;
581 struct io_buffer
*iobuf
;
582 unsigned long offset
;
586 offset
= ntohl ( data_out
->offset
);
587 len
= ISCSI_DATA_LEN ( data_out
->lengths
);
588 pad_len
= ISCSI_DATA_PAD_LEN ( data_out
->lengths
);
590 assert ( iscsi
->command
!= NULL
);
591 assert ( iscsi
->command
->data_out
);
592 assert ( ( offset
+ len
) <= iscsi
->command
->data_out_len
);
594 iobuf
= xfer_alloc_iob ( &iscsi
->socket
, ( len
+ pad_len
) );
598 copy_from_user ( iob_put ( iobuf
, len
),
599 iscsi
->command
->data_out
, offset
, len
);
600 memset ( iob_put ( iobuf
, pad_len
), 0, pad_len
);
602 return xfer_deliver_iob ( &iscsi
->socket
, iobuf
);
606 * Receive data segment of an iSCSI NOP-In
608 * @v iscsi iSCSI session
609 * @v data Received data
610 * @v len Length of received data
611 * @v remaining Data remaining after this data
612 * @ret rc Return status code
614 static int iscsi_rx_nop_in ( struct iscsi_session
*iscsi
,
615 const void *data __unused
, size_t len __unused
,
616 size_t remaining __unused
) {
617 struct iscsi_nop_in
*nop_in
= &iscsi
->rx_bhs
.nop_in
;
619 DBGC2 ( iscsi
, "iSCSI %p received NOP-In\n", iscsi
);
621 /* We don't currently have the ability to respond to NOP-Ins
622 * sent as ping requests, but we can happily accept NOP-Ins
623 * sent merely to update CmdSN.
625 if ( nop_in
->ttt
!= htonl ( ISCSI_TAG_RESERVED
) ) {
626 DBGC ( iscsi
, "iSCSI %p received unsupported NOP-In with TTT "
627 "%08x\n", iscsi
, ntohl ( nop_in
->ttt
) );
628 return -ENOTSUP_NOP_IN
;
634 /****************************************************************************
641 * Build iSCSI login request strings
643 * @v iscsi iSCSI session
645 * These are the initial set of strings sent in the first login
646 * request PDU. We want the following settings:
650 * MaxConnections is irrelevant; we make only one connection anyway [4]
652 * ImmediateData is irrelevant; we never send immediate data [4]
653 * MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
654 * MaxBurstLength=262144 (default; we don't care) [3]
655 * FirstBurstLength=262144 (default; we don't care)
656 * DefaultTime2Wait=0 [2]
657 * DefaultTime2Retain=0 [2]
658 * MaxOutstandingR2T=1
660 * DataSequenceInOrder=Yes
661 * ErrorRecoveryLevel=0
663 * [1] InitialR2T has an OR resolution function, so the target may
664 * force us to use it. We therefore simplify our logic by always
667 * [2] These ensure that we can safely start a new task once we have
668 * reconnected after a failure, without having to manually tidy up
671 * [3] We are quite happy to use the RFC-defined default values for
672 * these parameters, but some targets (notably OpenSolaris)
673 * incorrectly assume a default value of zero, so we explicitly
674 * specify the default values.
676 * [4] We are quite happy to use the RFC-defined default values for
677 * these parameters, but some targets (notably a QNAP TS-639Pro) fail
678 * unless they are supplied, so we explicitly specify the default
681 static int iscsi_build_login_request_strings ( struct iscsi_session
*iscsi
,
682 void *data
, size_t len
) {
683 unsigned int used
= 0;
684 const char *auth_method
;
686 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_SECURITY
) {
687 /* Default to allowing no authentication */
688 auth_method
= "None";
689 /* If we have a credential to supply, permit CHAP */
690 if ( iscsi
->initiator_username
)
691 auth_method
= "CHAP,None";
692 /* If we have a credential to check, force CHAP */
693 if ( iscsi
->target_username
)
694 auth_method
= "CHAP";
695 used
+= ssnprintf ( data
+ used
, len
- used
,
698 "SessionType=Normal%c"
700 iscsi
->initiator_iqn
, 0,
701 iscsi
->target_iqn
, 0, 0,
705 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_ALGORITHM
) {
706 used
+= ssnprintf ( data
+ used
, len
- used
, "CHAP_A=5%c", 0 );
709 if ( ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_RESPONSE
) ) {
710 char buf
[ base16_encoded_len ( iscsi
->chap
.response_len
) + 1 ];
711 assert ( iscsi
->initiator_username
!= NULL
);
712 base16_encode ( iscsi
->chap
.response
, iscsi
->chap
.response_len
,
713 buf
, sizeof ( buf
) );
714 used
+= ssnprintf ( data
+ used
, len
- used
,
715 "CHAP_N=%s%cCHAP_R=0x%s%c",
716 iscsi
->initiator_username
, 0, buf
, 0 );
719 if ( ( iscsi
->status
& ISCSI_STATUS_STRINGS_CHAP_CHALLENGE
) ) {
720 size_t challenge_len
= ( sizeof ( iscsi
->chap_challenge
) - 1 );
721 char buf
[ base16_encoded_len ( challenge_len
) + 1 ];
722 base16_encode ( ( iscsi
->chap_challenge
+ 1 ), challenge_len
,
723 buf
, sizeof ( buf
) );
724 used
+= ssnprintf ( data
+ used
, len
- used
,
725 "CHAP_I=%d%cCHAP_C=0x%s%c",
726 iscsi
->chap_challenge
[0], 0, buf
, 0 );
729 if ( iscsi
->status
& ISCSI_STATUS_STRINGS_OPERATIONAL
) {
730 used
+= ssnprintf ( data
+ used
, len
- used
,
731 "HeaderDigest=None%c"
736 "MaxRecvDataSegmentLength=8192%c"
737 "MaxBurstLength=262144%c"
738 "DefaultTime2Wait=0%c"
739 "DefaultTime2Retain=0%c"
740 "MaxOutstandingR2T=1%c"
741 "DataPDUInOrder=Yes%c"
742 "DataSequenceInOrder=Yes%c"
743 "ErrorRecoveryLevel=0%c",
744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
751 * Build iSCSI login request BHS
753 * @v iscsi iSCSI session
755 static void iscsi_start_login ( struct iscsi_session
*iscsi
) {
756 struct iscsi_bhs_login_request
*request
= &iscsi
->tx_bhs
.login_request
;
759 switch ( iscsi
->status
& ISCSI_LOGIN_CSG_MASK
) {
760 case ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION
:
761 DBGC ( iscsi
, "iSCSI %p entering security negotiation\n",
764 case ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION
:
765 DBGC ( iscsi
, "iSCSI %p entering operational negotiation\n",
772 /* Construct BHS and initiate transmission */
773 iscsi_start_tx ( iscsi
);
774 request
->opcode
= ( ISCSI_OPCODE_LOGIN_REQUEST
|
775 ISCSI_FLAG_IMMEDIATE
);
776 request
->flags
= ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) |
777 ISCSI_LOGIN_FLAG_TRANSITION
);
778 /* version_max and version_min left as zero */
779 len
= iscsi_build_login_request_strings ( iscsi
, NULL
, 0 );
780 ISCSI_SET_LENGTHS ( request
->lengths
, 0, len
);
781 request
->isid_iana_en
= htonl ( ISCSI_ISID_IANA
|
782 IANA_EN_FEN_SYSTEMS
);
783 request
->isid_iana_qual
= htons ( iscsi
->isid_iana_qual
);
784 /* tsih left as zero */
785 request
->itt
= htonl ( iscsi
->itt
);
786 /* cid left as zero */
787 request
->cmdsn
= htonl ( iscsi
->cmdsn
);
788 request
->expstatsn
= htonl ( iscsi
->statsn
+ 1 );
792 * Complete iSCSI login request PDU transmission
794 * @v iscsi iSCSI session
797 static void iscsi_login_request_done ( struct iscsi_session
*iscsi
) {
799 /* Clear any "strings to send" flags */
800 iscsi
->status
&= ~ISCSI_STATUS_STRINGS_MASK
;
802 /* Free any dynamically allocated storage used for login */
803 chap_finish ( &iscsi
->chap
);
807 * Transmit data segment of an iSCSI login request PDU
809 * @v iscsi iSCSI session
810 * @ret rc Return status code
812 * For login requests, the data segment consists of the login strings.
814 static int iscsi_tx_login_request ( struct iscsi_session
*iscsi
) {
815 struct iscsi_bhs_login_request
*request
= &iscsi
->tx_bhs
.login_request
;
816 struct io_buffer
*iobuf
;
820 len
= ISCSI_DATA_LEN ( request
->lengths
);
821 pad_len
= ISCSI_DATA_PAD_LEN ( request
->lengths
);
822 iobuf
= xfer_alloc_iob ( &iscsi
->socket
, ( len
+ pad_len
) );
825 iob_put ( iobuf
, len
);
826 iscsi_build_login_request_strings ( iscsi
, iobuf
->data
, len
);
827 memset ( iob_put ( iobuf
, pad_len
), 0, pad_len
);
829 return xfer_deliver_iob ( &iscsi
->socket
, iobuf
);
833 * Decode large binary value
835 * @v encoded Encoded large binary value
837 * @v len Length of data buffer
838 * @ret len Length of raw data, or negative error
840 static int iscsi_large_binary_decode ( const char *encoded
, uint8_t *raw
,
843 /* Check for initial '0x' or '0b' and decode as appropriate */
844 if ( *(encoded
++) == '0' ) {
845 switch ( tolower ( *(encoded
++) ) ) {
847 return base16_decode ( encoded
, raw
, len
);
849 return base64_decode ( encoded
, raw
, len
);
853 return -EPROTO_INVALID_LARGE_BINARY
;
857 * Handle iSCSI TargetAddress text value
859 * @v iscsi iSCSI session
860 * @v value TargetAddress value
861 * @ret rc Return status code
863 static int iscsi_handle_targetaddress_value ( struct iscsi_session
*iscsi
,
864 const char *value
) {
867 DBGC ( iscsi
, "iSCSI %p will redirect to %s\n", iscsi
, value
);
869 /* Replace target address */
870 free ( iscsi
->target_address
);
871 iscsi
->target_address
= strdup ( value
);
872 if ( ! iscsi
->target_address
)
875 /* Replace target port */
876 iscsi
->target_port
= htons ( ISCSI_PORT
);
877 separator
= strchr ( iscsi
->target_address
, ':' );
880 iscsi
->target_port
= strtoul ( ( separator
+ 1 ), NULL
, 0 );
887 * Handle iSCSI AuthMethod text value
889 * @v iscsi iSCSI session
890 * @v value AuthMethod value
891 * @ret rc Return status code
893 static int iscsi_handle_authmethod_value ( struct iscsi_session
*iscsi
,
894 const char *value
) {
896 /* If server requests CHAP, send the CHAP_A string */
897 if ( strcmp ( value
, "CHAP" ) == 0 ) {
898 DBGC ( iscsi
, "iSCSI %p initiating CHAP authentication\n",
900 iscsi
->status
|= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM
|
901 ISCSI_STATUS_AUTH_FORWARD_REQUIRED
);
908 * Handle iSCSI CHAP_A text value
910 * @v iscsi iSCSI session
911 * @v value CHAP_A value
912 * @ret rc Return status code
914 static int iscsi_handle_chap_a_value ( struct iscsi_session
*iscsi
,
915 const char *value
) {
917 /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
918 * the server responds with anything else it is a protocol
921 if ( strcmp ( value
, "5" ) != 0 ) {
922 DBGC ( iscsi
, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
924 return -EPROTO_INVALID_CHAP_ALGORITHM
;
931 * Handle iSCSI CHAP_I text value
933 * @v iscsi iSCSI session
934 * @v value CHAP_I value
935 * @ret rc Return status code
937 static int iscsi_handle_chap_i_value ( struct iscsi_session
*iscsi
,
938 const char *value
) {
939 unsigned int identifier
;
943 /* The CHAP identifier is an integer value */
944 identifier
= strtoul ( value
, &endp
, 0 );
945 if ( *endp
!= '\0' ) {
946 DBGC ( iscsi
, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
948 return -EPROTO_INVALID_CHAP_IDENTIFIER
;
951 /* Prepare for CHAP with MD5 */
952 chap_finish ( &iscsi
->chap
);
953 if ( ( rc
= chap_init ( &iscsi
->chap
, &md5_algorithm
) ) != 0 ) {
954 DBGC ( iscsi
, "iSCSI %p could not initialise CHAP: %s\n",
955 iscsi
, strerror ( rc
) );
959 /* Identifier and secret are the first two components of the
962 chap_set_identifier ( &iscsi
->chap
, identifier
);
963 if ( iscsi
->initiator_password
) {
964 chap_update ( &iscsi
->chap
, iscsi
->initiator_password
,
965 strlen ( iscsi
->initiator_password
) );
972 * Handle iSCSI CHAP_C text value
974 * @v iscsi iSCSI session
975 * @v value CHAP_C value
976 * @ret rc Return status code
978 static int iscsi_handle_chap_c_value ( struct iscsi_session
*iscsi
,
979 const char *value
) {
980 uint8_t buf
[ strlen ( value
) ]; /* Decoding never expands data */
985 /* Process challenge */
986 len
= iscsi_large_binary_decode ( value
, buf
, sizeof ( buf
) );
989 DBGC ( iscsi
, "iSCSI %p invalid CHAP challenge \"%s\": %s\n",
990 iscsi
, value
, strerror ( rc
) );
993 chap_update ( &iscsi
->chap
, buf
, len
);
995 /* Build CHAP response */
996 DBGC ( iscsi
, "iSCSI %p sending CHAP response\n", iscsi
);
997 chap_respond ( &iscsi
->chap
);
998 iscsi
->status
|= ISCSI_STATUS_STRINGS_CHAP_RESPONSE
;
1000 /* Send CHAP challenge, if applicable */
1001 if ( iscsi
->target_username
) {
1002 iscsi
->status
|= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE
;
1003 /* Generate CHAP challenge data */
1004 for ( i
= 0 ; i
< sizeof ( iscsi
->chap_challenge
) ; i
++ ) {
1005 iscsi
->chap_challenge
[i
] = random();
1013 * Handle iSCSI CHAP_N text value
1015 * @v iscsi iSCSI session
1016 * @v value CHAP_N value
1017 * @ret rc Return status code
1019 static int iscsi_handle_chap_n_value ( struct iscsi_session
*iscsi
,
1020 const char *value
) {
1022 /* The target username isn't actually involved at any point in
1023 * the authentication process; it merely serves to identify
1024 * which password the target is using to generate the CHAP
1025 * response. We unnecessarily verify that the username is as
1026 * expected, in order to provide mildly helpful diagnostics if
1027 * the target is supplying the wrong username/password
1030 if ( iscsi
->target_username
&&
1031 ( strcmp ( iscsi
->target_username
, value
) != 0 ) ) {
1032 DBGC ( iscsi
, "iSCSI %p target username \"%s\" incorrect "
1033 "(wanted \"%s\")\n",
1034 iscsi
, value
, iscsi
->target_username
);
1035 return -EACCES_INCORRECT_TARGET_USERNAME
;
1042 * Handle iSCSI CHAP_R text value
1044 * @v iscsi iSCSI session
1045 * @v value CHAP_R value
1046 * @ret rc Return status code
1048 static int iscsi_handle_chap_r_value ( struct iscsi_session
*iscsi
,
1049 const char *value
) {
1050 uint8_t buf
[ strlen ( value
) ]; /* Decoding never expands data */
1054 /* Generate CHAP response for verification */
1055 chap_finish ( &iscsi
->chap
);
1056 if ( ( rc
= chap_init ( &iscsi
->chap
, &md5_algorithm
) ) != 0 ) {
1057 DBGC ( iscsi
, "iSCSI %p could not initialise CHAP: %s\n",
1058 iscsi
, strerror ( rc
) );
1061 chap_set_identifier ( &iscsi
->chap
, iscsi
->chap_challenge
[0] );
1062 if ( iscsi
->target_password
) {
1063 chap_update ( &iscsi
->chap
, iscsi
->target_password
,
1064 strlen ( iscsi
->target_password
) );
1066 chap_update ( &iscsi
->chap
, &iscsi
->chap_challenge
[1],
1067 ( sizeof ( iscsi
->chap_challenge
) - 1 ) );
1068 chap_respond ( &iscsi
->chap
);
1070 /* Process response */
1071 len
= iscsi_large_binary_decode ( value
, buf
, sizeof ( buf
) );
1074 DBGC ( iscsi
, "iSCSI %p invalid CHAP response \"%s\": %s\n",
1075 iscsi
, value
, strerror ( rc
) );
1079 /* Check CHAP response */
1080 if ( len
!= ( int ) iscsi
->chap
.response_len
) {
1081 DBGC ( iscsi
, "iSCSI %p invalid CHAP response length\n",
1083 return -EPROTO_INVALID_CHAP_RESPONSE
;
1085 if ( memcmp ( buf
, iscsi
->chap
.response
, len
) != 0 ) {
1086 DBGC ( iscsi
, "iSCSI %p incorrect CHAP response \"%s\"\n",
1088 return -EACCES_INCORRECT_TARGET_PASSWORD
;
1091 /* Mark session as authenticated */
1092 iscsi
->status
|= ISCSI_STATUS_AUTH_REVERSE_OK
;
1097 /** An iSCSI text string that we want to handle */
1098 struct iscsi_string_type
{
1101 * This is the portion preceding the "=" sign,
1102 * e.g. "InitiatorName", "CHAP_A", etc.
1105 /** Handle iSCSI string value
1107 * @v iscsi iSCSI session
1108 * @v value iSCSI string value
1109 * @ret rc Return status code
1111 int ( * handle
) ( struct iscsi_session
*iscsi
, const char *value
);
1114 /** iSCSI text strings that we want to handle */
1115 static struct iscsi_string_type iscsi_string_types
[] = {
1116 { "TargetAddress", iscsi_handle_targetaddress_value
},
1117 { "AuthMethod", iscsi_handle_authmethod_value
},
1118 { "CHAP_A", iscsi_handle_chap_a_value
},
1119 { "CHAP_I", iscsi_handle_chap_i_value
},
1120 { "CHAP_C", iscsi_handle_chap_c_value
},
1121 { "CHAP_N", iscsi_handle_chap_n_value
},
1122 { "CHAP_R", iscsi_handle_chap_r_value
},
1127 * Handle iSCSI string
1129 * @v iscsi iSCSI session
1130 * @v string iSCSI string (in "key=value" format)
1131 * @ret rc Return status code
1133 static int iscsi_handle_string ( struct iscsi_session
*iscsi
,
1134 const char *string
) {
1135 struct iscsi_string_type
*type
;
1136 const char *separator
;
1141 /* Find separator */
1142 separator
= strchr ( string
, '=' );
1143 if ( ! separator
) {
1144 DBGC ( iscsi
, "iSCSI %p malformed string %s\n",
1146 return -EPROTO_INVALID_KEY_VALUE_PAIR
;
1148 key_len
= ( separator
- string
);
1149 value
= ( separator
+ 1 );
1151 /* Check for rejections. Since we send only non-rejectable
1152 * values, any rejection is a fatal protocol error.
1154 if ( strcmp ( value
, "Reject" ) == 0 ) {
1155 DBGC ( iscsi
, "iSCSI %p rejection: %s\n", iscsi
, string
);
1156 return -EPROTO_VALUE_REJECTED
;
1159 /* Handle key/value pair */
1160 for ( type
= iscsi_string_types
; type
->key
; type
++ ) {
1161 if ( strncmp ( string
, type
->key
, key_len
) != 0 )
1163 DBGC ( iscsi
, "iSCSI %p handling %s\n", iscsi
, string
);
1164 if ( ( rc
= type
->handle ( iscsi
, value
) ) != 0 ) {
1165 DBGC ( iscsi
, "iSCSI %p could not handle %s: %s\n",
1166 iscsi
, string
, strerror ( rc
) );
1171 DBGC ( iscsi
, "iSCSI %p ignoring %s\n", iscsi
, string
);
1176 * Handle iSCSI strings
1178 * @v iscsi iSCSI session
1179 * @v string iSCSI string buffer
1180 * @v len Length of string buffer
1181 * @ret rc Return status code
1183 static int iscsi_handle_strings ( struct iscsi_session
*iscsi
,
1184 const char *strings
, size_t len
) {
1188 /* Handle each string in turn, taking care not to overrun the
1189 * data buffer in case of badly-terminated data.
1192 string_len
= ( strnlen ( strings
, len
) + 1 );
1193 if ( string_len
> len
)
1195 if ( ( rc
= iscsi_handle_string ( iscsi
, strings
) ) != 0 )
1197 strings
+= string_len
;
1204 * Convert iSCSI response status to return status code
1206 * @v status_class iSCSI status class
1207 * @v status_detail iSCSI status detail
1208 * @ret rc Return status code
1210 static int iscsi_status_to_rc ( unsigned int status_class
,
1211 unsigned int status_detail
) {
1212 switch ( status_class
) {
1213 case ISCSI_STATUS_INITIATOR_ERROR
:
1214 switch ( status_detail
) {
1215 case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION
:
1216 return -EPERM_INITIATOR_AUTHENTICATION
;
1217 case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION
:
1218 return -EPERM_INITIATOR_AUTHORISATION
;
1219 case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND
:
1220 case ISCSI_STATUS_INITIATOR_ERROR_REMOVED
:
1223 return -ENOTSUP_INITIATOR_STATUS
;
1225 case ISCSI_STATUS_TARGET_ERROR
:
1226 switch ( status_detail
) {
1227 case ISCSI_STATUS_TARGET_ERROR_UNAVAILABLE
:
1228 return -EIO_TARGET_UNAVAILABLE
;
1229 case ISCSI_STATUS_TARGET_ERROR_NO_RESOURCES
:
1230 return -EIO_TARGET_NO_RESOURCES
;
1232 return -ENOTSUP_TARGET_STATUS
;
1240 * Receive data segment of an iSCSI login response PDU
1242 * @v iscsi iSCSI session
1243 * @v data Received data
1244 * @v len Length of received data
1245 * @v remaining Data remaining after this data
1246 * @ret rc Return status code
1248 static int iscsi_rx_login_response ( struct iscsi_session
*iscsi
,
1249 const void *data
, size_t len
,
1250 size_t remaining
) {
1251 struct iscsi_bhs_login_response
*response
1252 = &iscsi
->rx_bhs
.login_response
;
1255 /* Buffer up the PDU data */
1256 if ( ( rc
= iscsi_rx_buffered_data ( iscsi
, data
, len
) ) != 0 ) {
1257 DBGC ( iscsi
, "iSCSI %p could not buffer login response: %s\n",
1258 iscsi
, strerror ( rc
) );
1264 /* Process string data and discard string buffer */
1265 if ( ( rc
= iscsi_handle_strings ( iscsi
, iscsi
->rx_buffer
,
1266 iscsi
->rx_len
) ) != 0 )
1268 iscsi_rx_buffered_data_done ( iscsi
);
1270 /* Check for login redirection */
1271 if ( response
->status_class
== ISCSI_STATUS_REDIRECT
) {
1272 DBGC ( iscsi
, "iSCSI %p redirecting to new server\n", iscsi
);
1273 iscsi_close_connection ( iscsi
, 0 );
1274 if ( ( rc
= iscsi_open_connection ( iscsi
) ) != 0 ) {
1275 DBGC ( iscsi
, "iSCSI %p could not redirect: %s\n ",
1276 iscsi
, strerror ( rc
) );
1282 /* Check for fatal errors */
1283 if ( response
->status_class
!= 0 ) {
1284 DBGC ( iscsi
, "iSCSI login failure: class %02x detail %02x\n",
1285 response
->status_class
, response
->status_detail
);
1286 rc
= iscsi_status_to_rc ( response
->status_class
,
1287 response
->status_detail
);
1291 /* Handle login transitions */
1292 if ( response
->flags
& ISCSI_LOGIN_FLAG_TRANSITION
) {
1293 iscsi
->status
&= ~( ISCSI_STATUS_PHASE_MASK
|
1294 ISCSI_STATUS_STRINGS_MASK
);
1295 switch ( response
->flags
& ISCSI_LOGIN_NSG_MASK
) {
1296 case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION
:
1298 ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE
|
1299 ISCSI_STATUS_STRINGS_OPERATIONAL
);
1301 case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE
:
1302 iscsi
->status
|= ISCSI_STATUS_FULL_FEATURE_PHASE
;
1305 DBGC ( iscsi
, "iSCSI %p got invalid response flags "
1306 "%02x\n", iscsi
, response
->flags
);
1311 /* Send next login request PDU if we haven't reached the full
1312 * feature phase yet.
1314 if ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) !=
1315 ISCSI_STATUS_FULL_FEATURE_PHASE
) {
1316 iscsi_start_login ( iscsi
);
1320 /* Check that target authentication was successful (if required) */
1321 if ( ( iscsi
->status
& ISCSI_STATUS_AUTH_REVERSE_REQUIRED
) &&
1322 ! ( iscsi
->status
& ISCSI_STATUS_AUTH_REVERSE_OK
) ) {
1323 DBGC ( iscsi
, "iSCSI %p nefarious target tried to bypass "
1324 "authentication\n", iscsi
);
1328 /* Notify SCSI layer of window change */
1329 DBGC ( iscsi
, "iSCSI %p entering full feature phase\n", iscsi
);
1330 xfer_window_changed ( &iscsi
->control
);
1335 /****************************************************************************
1337 * iSCSI to socket interface
1344 * @v iscsi iSCSI session
1346 static void iscsi_tx_pause ( struct iscsi_session
*iscsi
) {
1347 process_del ( &iscsi
->process
);
1353 * @v iscsi iSCSI session
1355 static void iscsi_tx_resume ( struct iscsi_session
*iscsi
) {
1356 process_add ( &iscsi
->process
);
1360 * Start up a new TX PDU
1362 * @v iscsi iSCSI session
1364 * This initiates the process of sending a new PDU. Only one PDU may
1365 * be in transit at any one time.
1367 static void iscsi_start_tx ( struct iscsi_session
*iscsi
) {
1369 assert ( iscsi
->tx_state
== ISCSI_TX_IDLE
);
1371 /* Initialise TX BHS */
1372 memset ( &iscsi
->tx_bhs
, 0, sizeof ( iscsi
->tx_bhs
) );
1374 /* Flag TX engine to start transmitting */
1375 iscsi
->tx_state
= ISCSI_TX_BHS
;
1377 /* Start transmission process */
1378 iscsi_tx_resume ( iscsi
);
1384 * @v iscsi iSCSI session
1385 * @ret rc Return status code
1387 static int iscsi_tx_nothing ( struct iscsi_session
*iscsi __unused
) {
1392 * Transmit basic header segment of an iSCSI PDU
1394 * @v iscsi iSCSI session
1395 * @ret rc Return status code
1397 static int iscsi_tx_bhs ( struct iscsi_session
*iscsi
) {
1398 return xfer_deliver_raw ( &iscsi
->socket
, &iscsi
->tx_bhs
,
1399 sizeof ( iscsi
->tx_bhs
) );
1403 * Transmit data segment of an iSCSI PDU
1405 * @v iscsi iSCSI session
1406 * @ret rc Return status code
1408 * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
1409 * will be valid when this is called.
1411 static int iscsi_tx_data ( struct iscsi_session
*iscsi
) {
1412 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1414 switch ( common
->opcode
& ISCSI_OPCODE_MASK
) {
1415 case ISCSI_OPCODE_DATA_OUT
:
1416 return iscsi_tx_data_out ( iscsi
);
1417 case ISCSI_OPCODE_LOGIN_REQUEST
:
1418 return iscsi_tx_login_request ( iscsi
);
1420 /* Nothing to send in other states */
1426 * Complete iSCSI PDU transmission
1428 * @v iscsi iSCSI session
1430 * Called when a PDU has been completely transmitted and the TX state
1431 * machine is about to enter the idle state. iscsi::tx_bhs will be
1432 * valid for the just-completed PDU when this is called.
1434 static void iscsi_tx_done ( struct iscsi_session
*iscsi
) {
1435 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1437 /* Stop transmission process */
1438 iscsi_tx_pause ( iscsi
);
1440 switch ( common
->opcode
& ISCSI_OPCODE_MASK
) {
1441 case ISCSI_OPCODE_DATA_OUT
:
1442 iscsi_data_out_done ( iscsi
);
1444 case ISCSI_OPCODE_LOGIN_REQUEST
:
1445 iscsi_login_request_done ( iscsi
);
1454 * Transmit iSCSI PDU
1456 * @v iscsi iSCSI session
1457 * @v buf Temporary data buffer
1458 * @v len Length of temporary data buffer
1460 * Constructs data to be sent for the current TX state
1462 static void iscsi_tx_step ( struct iscsi_session
*iscsi
) {
1463 struct iscsi_bhs_common
*common
= &iscsi
->tx_bhs
.common
;
1464 int ( * tx
) ( struct iscsi_session
*iscsi
);
1465 enum iscsi_tx_state next_state
;
1469 /* Select fragment to transmit */
1471 switch ( iscsi
->tx_state
) {
1474 tx_len
= sizeof ( iscsi
->tx_bhs
);
1475 next_state
= ISCSI_TX_AHS
;
1478 tx
= iscsi_tx_nothing
;
1480 next_state
= ISCSI_TX_DATA
;
1484 tx_len
= ISCSI_DATA_LEN ( common
->lengths
);
1485 next_state
= ISCSI_TX_IDLE
;
1488 /* Nothing to do; pause processing */
1489 iscsi_tx_pause ( iscsi
);
1496 /* Check for window availability, if needed */
1497 if ( tx_len
&& ( xfer_window ( &iscsi
->socket
) == 0 ) ) {
1498 /* Cannot transmit at this point; pause
1499 * processing and wait for window to reopen
1501 iscsi_tx_pause ( iscsi
);
1506 if ( ( rc
= tx ( iscsi
) ) != 0 ) {
1507 DBGC ( iscsi
, "iSCSI %p could not transmit: %s\n",
1508 iscsi
, strerror ( rc
) );
1509 /* Transmission errors are fatal */
1510 iscsi_close ( iscsi
, rc
);
1514 /* Move to next state */
1515 iscsi
->tx_state
= next_state
;
1517 /* If we have moved to the idle state, mark
1518 * transmission as complete
1520 if ( iscsi
->tx_state
== ISCSI_TX_IDLE
)
1521 iscsi_tx_done ( iscsi
);
1525 /** iSCSI TX process descriptor */
1526 static struct process_descriptor iscsi_process_desc
=
1527 PROC_DESC ( struct iscsi_session
, process
, iscsi_tx_step
);
1530 * Receive basic header segment of an iSCSI PDU
1532 * @v iscsi iSCSI session
1533 * @v data Received data
1534 * @v len Length of received data
1535 * @v remaining Data remaining after this data
1536 * @ret rc Return status code
1538 * This fills in iscsi::rx_bhs with the data from the BHS portion of
1541 static int iscsi_rx_bhs ( struct iscsi_session
*iscsi
, const void *data
,
1542 size_t len
, size_t remaining __unused
) {
1543 memcpy ( &iscsi
->rx_bhs
.bytes
[iscsi
->rx_offset
], data
, len
);
1544 if ( ( iscsi
->rx_offset
+ len
) >= sizeof ( iscsi
->rx_bhs
) ) {
1545 DBGC2 ( iscsi
, "iSCSI %p received PDU opcode %#x len %#x\n",
1546 iscsi
, iscsi
->rx_bhs
.common
.opcode
,
1547 ISCSI_DATA_LEN ( iscsi
->rx_bhs
.common
.lengths
) );
1553 * Discard portion of an iSCSI PDU.
1555 * @v iscsi iSCSI session
1556 * @v data Received data
1557 * @v len Length of received data
1558 * @v remaining Data remaining after this data
1559 * @ret rc Return status code
1561 * This discards data from a portion of a received PDU.
1563 static int iscsi_rx_discard ( struct iscsi_session
*iscsi __unused
,
1564 const void *data __unused
, size_t len __unused
,
1565 size_t remaining __unused
) {
1571 * Receive data segment of an iSCSI PDU
1573 * @v iscsi iSCSI session
1574 * @v data Received data
1575 * @v len Length of received data
1576 * @v remaining Data remaining after this data
1577 * @ret rc Return status code
1579 * Handle processing of part of a PDU data segment. iscsi::rx_bhs
1580 * will be valid when this is called.
1582 static int iscsi_rx_data ( struct iscsi_session
*iscsi
, const void *data
,
1583 size_t len
, size_t remaining
) {
1584 struct iscsi_bhs_common_response
*response
1585 = &iscsi
->rx_bhs
.common_response
;
1587 /* Update cmdsn and statsn */
1588 iscsi
->cmdsn
= ntohl ( response
->expcmdsn
);
1589 iscsi
->statsn
= ntohl ( response
->statsn
);
1591 switch ( response
->opcode
& ISCSI_OPCODE_MASK
) {
1592 case ISCSI_OPCODE_LOGIN_RESPONSE
:
1593 return iscsi_rx_login_response ( iscsi
, data
, len
, remaining
);
1594 case ISCSI_OPCODE_SCSI_RESPONSE
:
1595 return iscsi_rx_scsi_response ( iscsi
, data
, len
, remaining
);
1596 case ISCSI_OPCODE_DATA_IN
:
1597 return iscsi_rx_data_in ( iscsi
, data
, len
, remaining
);
1598 case ISCSI_OPCODE_R2T
:
1599 return iscsi_rx_r2t ( iscsi
, data
, len
, remaining
);
1600 case ISCSI_OPCODE_NOP_IN
:
1601 return iscsi_rx_nop_in ( iscsi
, data
, len
, remaining
);
1605 DBGC ( iscsi
, "iSCSI %p unknown opcode %02x\n", iscsi
,
1607 return -ENOTSUP_OPCODE
;
1614 * @v iscsi iSCSI session
1615 * @v iobuf I/O buffer
1616 * @v meta Data transfer metadata
1617 * @ret rc Return status code
1619 * This handles received PDUs. The receive strategy is to fill in
1620 * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
1621 * throw away any AHS portion, and then process each part of the data
1622 * portion as it arrives. The data processing routine therefore
1623 * always has a full copy of the BHS available, even for portions of
1624 * the data in different packets to the BHS.
1626 static int iscsi_socket_deliver ( struct iscsi_session
*iscsi
,
1627 struct io_buffer
*iobuf
,
1628 struct xfer_metadata
*meta __unused
) {
1629 struct iscsi_bhs_common
*common
= &iscsi
->rx_bhs
.common
;
1630 int ( * rx
) ( struct iscsi_session
*iscsi
, const void *data
,
1631 size_t len
, size_t remaining
);
1632 enum iscsi_rx_state next_state
;
1638 switch ( iscsi
->rx_state
) {
1641 iscsi
->rx_len
= sizeof ( iscsi
->rx_bhs
);
1642 next_state
= ISCSI_RX_AHS
;
1645 rx
= iscsi_rx_discard
;
1646 iscsi
->rx_len
= 4 * ISCSI_AHS_LEN ( common
->lengths
);
1647 next_state
= ISCSI_RX_DATA
;
1651 iscsi
->rx_len
= ISCSI_DATA_LEN ( common
->lengths
);
1652 next_state
= ISCSI_RX_DATA_PADDING
;
1654 case ISCSI_RX_DATA_PADDING
:
1655 rx
= iscsi_rx_discard
;
1656 iscsi
->rx_len
= ISCSI_DATA_PAD_LEN ( common
->lengths
);
1657 next_state
= ISCSI_RX_BHS
;
1665 frag_len
= iscsi
->rx_len
- iscsi
->rx_offset
;
1666 if ( frag_len
> iob_len ( iobuf
) )
1667 frag_len
= iob_len ( iobuf
);
1668 remaining
= iscsi
->rx_len
- iscsi
->rx_offset
- frag_len
;
1669 if ( ( rc
= rx ( iscsi
, iobuf
->data
, frag_len
,
1670 remaining
) ) != 0 ) {
1671 DBGC ( iscsi
, "iSCSI %p could not process received "
1672 "data: %s\n", iscsi
, strerror ( rc
) );
1676 iscsi
->rx_offset
+= frag_len
;
1677 iob_pull ( iobuf
, frag_len
);
1679 /* If all the data for this state has not yet been
1680 * received, stay in this state for now.
1682 if ( iscsi
->rx_offset
!= iscsi
->rx_len
) {
1687 iscsi
->rx_state
= next_state
;
1688 iscsi
->rx_offset
= 0;
1692 /* Free I/O buffer */
1695 /* Destroy session on error */
1697 iscsi_close ( iscsi
, rc
);
1703 * Handle redirection event
1705 * @v iscsi iSCSI session
1706 * @v type Location type
1707 * @v args Remaining arguments depend upon location type
1708 * @ret rc Return status code
1710 static int iscsi_vredirect ( struct iscsi_session
*iscsi
, int type
,
1713 struct sockaddr
*peer
;
1716 /* Intercept redirects to a LOCATION_SOCKET and record the IP
1717 * address for the iBFT. This is a bit of a hack, but avoids
1718 * inventing an ioctl()-style call to retrieve the socket
1719 * address from a data-xfer interface.
1721 if ( type
== LOCATION_SOCKET
) {
1722 va_copy ( tmp
, args
);
1723 ( void ) va_arg ( tmp
, int ); /* Discard "semantics" */
1724 peer
= va_arg ( tmp
, struct sockaddr
* );
1725 memcpy ( &iscsi
->target_sockaddr
, peer
,
1726 sizeof ( iscsi
->target_sockaddr
) );
1730 /* Redirect to new location */
1731 if ( ( rc
= xfer_vreopen ( &iscsi
->socket
, type
, args
) ) != 0 )
1737 iscsi_close ( iscsi
, rc
);
1741 /** iSCSI socket interface operations */
1742 static struct interface_operation iscsi_socket_operations
[] = {
1743 INTF_OP ( xfer_deliver
, struct iscsi_session
*, iscsi_socket_deliver
),
1744 INTF_OP ( xfer_window_changed
, struct iscsi_session
*,
1746 INTF_OP ( xfer_vredirect
, struct iscsi_session
*, iscsi_vredirect
),
1747 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_close
),
1750 /** iSCSI socket interface descriptor */
1751 static struct interface_descriptor iscsi_socket_desc
=
1752 INTF_DESC ( struct iscsi_session
, socket
, iscsi_socket_operations
);
1754 /****************************************************************************
1756 * iSCSI command issuing
1761 * Check iSCSI flow-control window
1763 * @v iscsi iSCSI session
1764 * @ret len Length of window
1766 static size_t iscsi_scsi_window ( struct iscsi_session
*iscsi
) {
1768 if ( ( ( iscsi
->status
& ISCSI_STATUS_PHASE_MASK
) ==
1769 ISCSI_STATUS_FULL_FEATURE_PHASE
) &&
1770 ( iscsi
->command
== NULL
) ) {
1771 /* We cannot handle concurrent commands */
1779 * Issue iSCSI SCSI command
1781 * @v iscsi iSCSI session
1782 * @v parent Parent interface
1783 * @v command SCSI command
1784 * @ret tag Command tag, or negative error
1786 static int iscsi_scsi_command ( struct iscsi_session
*iscsi
,
1787 struct interface
*parent
,
1788 struct scsi_cmd
*command
) {
1790 /* This iSCSI implementation cannot handle multiple concurrent
1791 * commands or commands arriving before login is complete.
1793 if ( iscsi_scsi_window ( iscsi
) == 0 ) {
1794 DBGC ( iscsi
, "iSCSI %p cannot handle concurrent commands\n",
1800 iscsi
->command
= malloc ( sizeof ( *command
) );
1801 if ( ! iscsi
->command
)
1803 memcpy ( iscsi
->command
, command
, sizeof ( *command
) );
1805 /* Assign new ITT */
1806 iscsi_new_itt ( iscsi
);
1808 /* Start sending command */
1809 iscsi_start_command ( iscsi
);
1811 /* Attach to parent interface and return */
1812 intf_plug_plug ( &iscsi
->data
, parent
);
1816 /** iSCSI SCSI command-issuing interface operations */
1817 static struct interface_operation iscsi_control_op
[] = {
1818 INTF_OP ( scsi_command
, struct iscsi_session
*, iscsi_scsi_command
),
1819 INTF_OP ( xfer_window
, struct iscsi_session
*, iscsi_scsi_window
),
1820 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_close
),
1821 INTF_OP ( acpi_describe
, struct iscsi_session
*, ibft_describe
),
1824 /** iSCSI SCSI command-issuing interface descriptor */
1825 static struct interface_descriptor iscsi_control_desc
=
1826 INTF_DESC ( struct iscsi_session
, control
, iscsi_control_op
);
1829 * Close iSCSI command
1831 * @v iscsi iSCSI session
1832 * @v rc Reason for close
1834 static void iscsi_command_close ( struct iscsi_session
*iscsi
, int rc
) {
1836 /* Restart interface */
1837 intf_restart ( &iscsi
->data
, rc
);
1839 /* Treat unsolicited command closures mid-command as fatal,
1840 * because we have no code to handle partially-completed PDUs.
1842 if ( iscsi
->command
!= NULL
)
1843 iscsi_close ( iscsi
, ( ( rc
== 0 ) ?
-ECANCELED
: rc
) );
1846 /** iSCSI SCSI command interface operations */
1847 static struct interface_operation iscsi_data_op
[] = {
1848 INTF_OP ( intf_close
, struct iscsi_session
*, iscsi_command_close
),
1851 /** iSCSI SCSI command interface descriptor */
1852 static struct interface_descriptor iscsi_data_desc
=
1853 INTF_DESC ( struct iscsi_session
, data
, iscsi_data_op
);
1855 /****************************************************************************
1861 /** iSCSI root path components (as per RFC4173) */
1862 enum iscsi_root_path_component
{
1871 /** iSCSI initiator IQN setting */
1872 const struct setting initiator_iqn_setting
__setting ( SETTING_SANBOOT_EXTRA
,
1874 .name
= "initiator-iqn",
1875 .description
= "iSCSI initiator name",
1876 .tag
= DHCP_ISCSI_INITIATOR_IQN
,
1877 .type
= &setting_type_string
,
1880 /** iSCSI reverse username setting */
1881 const struct setting reverse_username_setting
__setting ( SETTING_AUTH_EXTRA
,
1882 reverse
-username
) = {
1883 .name
= "reverse-username",
1884 .description
= "Reverse user name",
1885 .tag
= DHCP_EB_REVERSE_USERNAME
,
1886 .type
= &setting_type_string
,
1889 /** iSCSI reverse password setting */
1890 const struct setting reverse_password_setting
__setting ( SETTING_AUTH_EXTRA
,
1891 reverse
-password
) = {
1892 .name
= "reverse-password",
1893 .description
= "Reverse password",
1894 .tag
= DHCP_EB_REVERSE_PASSWORD
,
1895 .type
= &setting_type_string
,
1899 * Parse iSCSI root path
1901 * @v iscsi iSCSI session
1902 * @v root_path iSCSI root path (as per RFC4173)
1903 * @ret rc Return status code
1905 static int iscsi_parse_root_path ( struct iscsi_session
*iscsi
,
1906 const char *root_path
) {
1907 char rp_copy
[ strlen ( root_path
) + 1 ];
1908 char *rp_comp
[NUM_RP_COMPONENTS
];
1913 /* Split root path into component parts */
1914 strcpy ( rp_copy
, root_path
);
1917 if ( i
== NUM_RP_COMPONENTS
)
1919 for ( ; *rp
!= ':' ; rp
++ ) {
1921 DBGC ( iscsi
, "iSCSI %p root path \"%s\" "
1922 "too short\n", iscsi
, root_path
);
1923 return -EINVAL_ROOT_PATH_TOO_SHORT
;
1929 /* Use root path components to configure iSCSI session */
1930 iscsi
->target_address
= strdup ( rp_comp
[RP_SERVERNAME
] );
1931 if ( ! iscsi
->target_address
)
1933 iscsi
->target_port
= strtoul ( rp_comp
[RP_PORT
], NULL
, 10 );
1934 if ( ! iscsi
->target_port
)
1935 iscsi
->target_port
= ISCSI_PORT
;
1936 if ( ( rc
= scsi_parse_lun ( rp_comp
[RP_LUN
], &iscsi
->lun
) ) != 0 ) {
1937 DBGC ( iscsi
, "iSCSI %p invalid LUN \"%s\"\n",
1938 iscsi
, rp_comp
[RP_LUN
] );
1941 iscsi
->target_iqn
= strdup ( rp_comp
[RP_TARGETNAME
] );
1942 if ( ! iscsi
->target_iqn
)
1949 * Fetch iSCSI settings
1951 * @v iscsi iSCSI session
1952 * @ret rc Return status code
1954 static int iscsi_fetch_settings ( struct iscsi_session
*iscsi
) {
1959 /* Fetch relevant settings. Don't worry about freeing on
1960 * error, since iscsi_free() will take care of that anyway.
1962 fetch_string_setting_copy ( NULL
, &username_setting
,
1963 &iscsi
->initiator_username
);
1964 fetch_string_setting_copy ( NULL
, &password_setting
,
1965 &iscsi
->initiator_password
);
1966 fetch_string_setting_copy ( NULL
, &reverse_username_setting
,
1967 &iscsi
->target_username
);
1968 fetch_string_setting_copy ( NULL
, &reverse_password_setting
,
1969 &iscsi
->target_password
);
1971 /* Use explicit initiator IQN if provided */
1972 fetch_string_setting_copy ( NULL
, &initiator_iqn_setting
,
1973 &iscsi
->initiator_iqn
);
1974 if ( iscsi
->initiator_iqn
)
1977 /* Otherwise, try to construct an initiator IQN from the hostname */
1978 fetch_string_setting_copy ( NULL
, &hostname_setting
, &hostname
);
1980 len
= asprintf ( &iscsi
->initiator_iqn
,
1981 ISCSI_DEFAULT_IQN_PREFIX
":%s", hostname
);
1984 DBGC ( iscsi
, "iSCSI %p could not allocate initiator "
1988 assert ( iscsi
->initiator_iqn
);
1992 /* Otherwise, try to construct an initiator IQN from the UUID */
1993 if ( ( len
= fetch_uuid_setting ( NULL
, &uuid_setting
, &uuid
) ) < 0 ) {
1994 DBGC ( iscsi
, "iSCSI %p has no suitable initiator IQN\n",
1996 return -EINVAL_NO_INITIATOR_IQN
;
1998 if ( ( len
= asprintf ( &iscsi
->initiator_iqn
,
1999 ISCSI_DEFAULT_IQN_PREFIX
":%s",
2000 uuid_ntoa ( &uuid
) ) ) < 0 ) {
2001 DBGC ( iscsi
, "iSCSI %p could not allocate initiator IQN\n",
2005 assert ( iscsi
->initiator_iqn
);
2012 * Check iSCSI authentication details
2014 * @v iscsi iSCSI session
2015 * @ret rc Return status code
2017 static int iscsi_check_auth ( struct iscsi_session
*iscsi
) {
2019 /* Check for invalid authentication combinations */
2020 if ( ( /* Initiator username without password (or vice-versa) */
2021 ( !! iscsi
->initiator_username
) ^
2022 ( !! iscsi
->initiator_password
) ) ||
2023 ( /* Target username without password (or vice-versa) */
2024 ( !! iscsi
->target_username
) ^
2025 ( !! iscsi
->target_password
) ) ||
2026 ( /* Target (reverse) without initiator (forward) */
2027 ( iscsi
->target_username
&&
2028 ( ! iscsi
->initiator_username
) ) ) ) {
2029 DBGC ( iscsi
, "iSCSI %p invalid credentials: initiator "
2030 "%sname,%spw, target %sname,%spw\n", iscsi
,
2031 ( iscsi
->initiator_username ?
"" : "no " ),
2032 ( iscsi
->initiator_password ?
"" : "no " ),
2033 ( iscsi
->target_username ?
"" : "no " ),
2034 ( iscsi
->target_password ?
"" : "no " ) );
2035 return -EINVAL_BAD_CREDENTIAL_MIX
;
2044 * @v parent Parent interface
2046 * @ret rc Return status code
2048 static int iscsi_open ( struct interface
*parent
, struct uri
*uri
) {
2049 struct iscsi_session
*iscsi
;
2053 if ( ! uri
->opaque
) {
2054 rc
= -EINVAL_NO_ROOT_PATH
;
2055 goto err_sanity_uri
;
2058 /* Allocate and initialise structure */
2059 iscsi
= zalloc ( sizeof ( *iscsi
) );
2064 ref_init ( &iscsi
->refcnt
, iscsi_free
);
2065 intf_init ( &iscsi
->control
, &iscsi_control_desc
, &iscsi
->refcnt
);
2066 intf_init ( &iscsi
->data
, &iscsi_data_desc
, &iscsi
->refcnt
);
2067 intf_init ( &iscsi
->socket
, &iscsi_socket_desc
, &iscsi
->refcnt
);
2068 process_init_stopped ( &iscsi
->process
, &iscsi_process_desc
,
2071 /* Parse root path */
2072 if ( ( rc
= iscsi_parse_root_path ( iscsi
, uri
->opaque
) ) != 0 )
2073 goto err_parse_root_path
;
2074 /* Set fields not specified by root path */
2075 if ( ( rc
= iscsi_fetch_settings ( iscsi
) ) != 0 )
2076 goto err_fetch_settings
;
2077 /* Validate authentication */
2078 if ( ( rc
= iscsi_check_auth ( iscsi
) ) != 0 )
2079 goto err_check_auth
;
2082 if ( ! iscsi
->target_address
) {
2083 DBGC ( iscsi
, "iSCSI %p does not yet support discovery\n",
2085 rc
= -ENOTSUP_DISCOVERY
;
2086 goto err_sanity_address
;
2088 if ( ! iscsi
->target_iqn
) {
2089 DBGC ( iscsi
, "iSCSI %p no target address supplied in %s\n",
2090 iscsi
, uri
->opaque
);
2091 rc
= -EINVAL_NO_TARGET_IQN
;
2092 goto err_sanity_iqn
;
2094 DBGC ( iscsi
, "iSCSI %p initiator %s\n",iscsi
, iscsi
->initiator_iqn
);
2095 DBGC ( iscsi
, "iSCSI %p target %s %s\n",
2096 iscsi
, iscsi
->target_address
, iscsi
->target_iqn
);
2099 if ( ( rc
= iscsi_open_connection ( iscsi
) ) != 0 )
2100 goto err_open_connection
;
2102 /* Attach SCSI device to parent interface */
2103 if ( ( rc
= scsi_open ( parent
, &iscsi
->control
,
2104 &iscsi
->lun
) ) != 0 ) {
2105 DBGC ( iscsi
, "iSCSI %p could not create SCSI device: %s\n",
2106 iscsi
, strerror ( rc
) );
2110 /* Mortalise self, and return */
2111 ref_put ( &iscsi
->refcnt
);
2115 err_open_connection
:
2120 err_parse_root_path
:
2121 iscsi_close ( iscsi
, rc
);
2122 ref_put ( &iscsi
->refcnt
);
2128 /** iSCSI URI opener */
2129 struct uri_opener iscsi_uri_opener __uri_opener
= {