10 FILE_LICENCE ( GPL2_OR_LATER );
13 #include <ipxe/socket.h>
14 #include <ipxe/scsi.h>
15 #include <ipxe/chap.h>
16 #include <ipxe/refcnt.h>
17 #include <ipxe/xfer.h>
18 #include <ipxe/process.h>
20 /** Default iSCSI port */
21 #define ISCSI_PORT 3260
24 * iSCSI segment lengths
26 * iSCSI uses an icky structure with one one-byte field (a dword
27 * count) and one three-byte field (a byte count). This structure,
28 * and the accompanying macros, relieve some of the pain.
30 union iscsi_segment_lengths {
32 /** The AHS length (measured in dwords) */
34 /** The data length (measured in bytes), in network
39 /** The data length (measured in bytes), in network byte
40 * order, with ahs_len as the first byte.
42 uint32_t ahs_and_data_len;
45 /** The length of the additional header segment, in dwords */
46 #define ISCSI_AHS_LEN( segment_lengths ) \
47 ( (segment_lengths).bytes.ahs_len )
49 /** The length of the data segment, in bytes, excluding any padding */
50 #define ISCSI_DATA_LEN( segment_lengths ) \
51 ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
53 /** The padding of the data segment, in bytes */
54 #define ISCSI_DATA_PAD_LEN( segment_lengths ) \
55 ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
57 /** Set additional header and data segment lengths */
58 #define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
59 (segment_lengths).ahs_and_data_len = \
60 htonl ( data_len | ( ahs_len << 24 ) ); \
64 * iSCSI basic header segment common fields
67 struct iscsi_bhs_common {
72 /** Fields specific to the PDU type */
74 /** Segment lengths */
75 union iscsi_segment_lengths lengths;
76 /** Fields specific to the PDU type */
78 /** Initiator Task Tag */
80 /** Fields specific to the PDU type */
85 #define ISCSI_OPCODE_MASK 0x3f
87 /** Immediate delivery */
88 #define ISCSI_FLAG_IMMEDIATE 0x40
90 /** Final PDU of a sequence */
91 #define ISCSI_FLAG_FINAL 0x80
93 /** iSCSI tag magic marker */
94 #define ISCSI_TAG_MAGIC 0x18ae0000
96 /** iSCSI reserved tag value */
97 #define ISCSI_TAG_RESERVED 0xffffffff
100 * iSCSI basic header segment common request fields
103 struct iscsi_bhs_common_response {
108 /** Fields specific to the PDU type */
110 /** Segment lengths */
111 union iscsi_segment_lengths lengths;
112 /** Fields specific to the PDU type */
114 /** Initiator Task Tag */
116 /** Fields specific to the PDU type */
118 /** Status sequence number */
120 /** Expected command sequence number */
122 /** Fields specific to the PDU type */
127 * iSCSI login request basic header segment
130 struct iscsi_bhs_login_request {
135 /** Maximum supported version number */
137 /** Minimum supported version number */
139 /** Segment lengths */
140 union iscsi_segment_lengths lengths;
141 /** Initiator session ID (IANA format) enterprise number and flags */
142 uint32_t isid_iana_en;
143 /** Initiator session ID (IANA format) qualifier */
144 uint16_t isid_iana_qual;
145 /** Target session identifying handle */
147 /** Initiator Task Tag */
153 /** Command sequence number */
155 /** Expected status sequence number */
158 uint8_t reserved_b[16];
161 /** Login request opcode */
162 #define ISCSI_OPCODE_LOGIN_REQUEST 0x03
164 /** Willingness to transition to next stage */
165 #define ISCSI_LOGIN_FLAG_TRANSITION 0x80
167 /** Key=value pairs continued in subsequent request */
168 #define ISCSI_LOGIN_FLAG_CONTINUE 0x40
170 /* Current stage values and mask */
171 #define ISCSI_LOGIN_CSG_MASK 0x0c
172 #define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
173 #define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
174 #define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
176 /* Next stage values and mask */
177 #define ISCSI_LOGIN_NSG_MASK 0x03
178 #define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
179 #define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
180 #define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
182 /** ISID IANA format marker */
183 #define ISCSI_ISID_IANA 0x40000000
185 /** Fen Systems Ltd. IANA enterprise number
187 * Permission is hereby granted to use Fen Systems Ltd.'s IANA
188 * enterprise number with this iSCSI implementation.
190 #define IANA_EN_FEN_SYSTEMS 10019
193 * iSCSI login response basic header segment
196 struct iscsi_bhs_login_response {
201 /** Maximum supported version number */
203 /** Minimum supported version number */
205 /** Segment lengths */
206 union iscsi_segment_lengths lengths;
207 /** Initiator session ID (IANA format) enterprise number and flags */
208 uint32_t isid_iana_en;
209 /** Initiator session ID (IANA format) qualifier */
210 uint16_t isid_iana_qual;
211 /** Target session identifying handle */
213 /** Initiator Task Tag */
217 /** Status sequence number */
219 /** Expected command sequence number */
221 /** Maximum command sequence number */
224 uint8_t status_class;
226 uint8_t status_detail;
228 uint8_t reserved_b[10];
231 /** Login response opcode */
232 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
234 /* Login response status codes */
235 #define ISCSI_STATUS_SUCCESS 0x00
236 #define ISCSI_STATUS_REDIRECT 0x01
237 #define ISCSI_STATUS_INITIATOR_ERROR 0x02
238 #define ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION 0x01
239 #define ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION 0x02
240 #define ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND 0x03
241 #define ISCSI_STATUS_INITIATOR_ERROR_REMOVED 0x04
242 #define ISCSI_STATUS_TARGET_ERROR 0x03
243 #define ISCSI_STATUS_TARGET_ERROR_UNAVAILABLE 0x01
244 #define ISCSI_STATUS_TARGET_ERROR_NO_RESOURCES 0x02
247 * iSCSI SCSI command basic header segment
250 struct iscsi_bhs_scsi_command {
257 /** Segment lengths */
258 union iscsi_segment_lengths lengths;
259 /** SCSI Logical Unit Number */
261 /** Initiator Task Tag */
263 /** Expected data transfer length */
265 /** Command sequence number */
267 /** Expected status sequence number */
269 /** SCSI Command Descriptor Block (CDB) */
273 /** SCSI command opcode */
274 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
276 /** Command will read data */
277 #define ISCSI_COMMAND_FLAG_READ 0x40
279 /** Command will write data */
280 #define ISCSI_COMMAND_FLAG_WRITE 0x20
282 /* Task attributes */
283 #define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
284 #define ISCSI_COMMAND_ATTR_SIMPLE 0x01
285 #define ISCSI_COMMAND_ATTR_ORDERED 0x02
286 #define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
287 #define ISCSI_COMMAND_ATTR_ACA 0x04
290 * iSCSI SCSI response basic header segment
293 struct iscsi_bhs_scsi_response {
300 /** SCSI status code */
302 /** Segment lengths */
303 union iscsi_segment_lengths lengths;
305 uint8_t reserved_a[8];
306 /** Initiator Task Tag */
310 /** Status sequence number */
312 /** Expected command sequence number */
314 /** Maximum command sequence number */
316 /** Expected data sequence number */
318 /** Bidirectional read residual count */
319 uint32_t bidi_residual_count;
320 /** Residual count */
321 uint32_t residual_count;
324 /** SCSI response opcode */
325 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
327 /** SCSI command completed at target */
328 #define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
330 /** SCSI target failure */
331 #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
333 /** Data overflow occurred */
334 #define ISCSI_RESPONSE_FLAG_OVERFLOW 0x20
336 /** Data underflow occurred */
337 #define ISCSI_RESPONSE_FLAG_UNDERFLOW 0x40
340 * iSCSI data-in basic header segment
343 struct iscsi_bhs_data_in {
350 /** SCSI status code */
352 /** Segment lengths */
353 union iscsi_segment_lengths lengths;
354 /** Logical Unit Number */
356 /** Initiator Task Tag */
358 /** Target Transfer Tag */
360 /** Status sequence number */
362 /** Expected command sequence number */
364 /** Maximum command sequence number */
366 /** Data sequence number */
370 /** Residual count */
371 uint32_t residual_count;
374 /** Data-in opcode */
375 #define ISCSI_OPCODE_DATA_IN 0x25
377 /** Data requires acknowledgement */
378 #define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
380 /** Data overflow occurred */
381 #define ISCSI_DATA_FLAG_OVERFLOW 0x04
383 /** Data underflow occurred */
384 #define ISCSI_DATA_FLAG_UNDERFLOW 0x02
386 /** SCSI status code and overflow/underflow flags are valid */
387 #define ISCSI_DATA_FLAG_STATUS 0x01
390 * iSCSI data-out basic header segment
393 struct iscsi_bhs_data_out {
400 /** Segment lengths */
401 union iscsi_segment_lengths lengths;
402 /** Logical Unit Number */
404 /** Initiator Task Tag */
406 /** Target Transfer Tag */
410 /** Expected status sequence number */
414 /** Data sequence number */
422 /** Data-out opcode */
423 #define ISCSI_OPCODE_DATA_OUT 0x05
426 * iSCSI request to transfer basic header segment
429 struct iscsi_bhs_r2t {
436 /** Segment lengths */
437 union iscsi_segment_lengths lengths;
438 /** Logical Unit Number */
440 /** Initiator Task Tag */
442 /** Target Transfer Tag */
444 /** Status sequence number */
446 /** Expected command sequence number */
448 /** Maximum command sequence number */
450 /** R2T sequence number */
454 /** Desired data transfer length */
459 #define ISCSI_OPCODE_R2T 0x31
462 * iSCSI NOP-In basic header segment
465 struct iscsi_nop_in {
469 uint8_t reserved_a[3];
470 /** Segment lengths */
471 union iscsi_segment_lengths lengths;
472 /** Logical Unit Number */
474 /** Initiator Task Tag */
476 /** Target Transfer Tag */
478 /** Status sequence number */
480 /** Expected command sequence number */
482 /** Maximum command sequence number */
485 uint8_t reserved_b[12];
489 #define ISCSI_OPCODE_NOP_IN 0x20
492 * An iSCSI basic header segment
495 struct iscsi_bhs_common common;
496 struct iscsi_bhs_common_response common_response;
497 struct iscsi_bhs_login_request login_request;
498 struct iscsi_bhs_login_response login_response;
499 struct iscsi_bhs_scsi_command scsi_command;
500 struct iscsi_bhs_scsi_response scsi_response;
501 struct iscsi_bhs_data_in data_in;
502 struct iscsi_bhs_data_out data_out;
503 struct iscsi_bhs_r2t r2t;
504 struct iscsi_nop_in nop_in;
505 unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
508 /** State of an iSCSI TX engine */
509 enum iscsi_tx_state {
510 /** Nothing to send */
512 /** Sending the basic header segment */
514 /** Sending the additional header segment */
516 /** Sending the data segment */
520 /** State of an iSCSI RX engine */
521 enum iscsi_rx_state {
522 /** Receiving the basic header segment */
524 /** Receiving the additional header segment */
526 /** Receiving the data segment */
528 /** Receiving the data segment padding */
529 ISCSI_RX_DATA_PADDING,
532 /** An iSCSI session */
533 struct iscsi_session {
534 /** Reference counter */
535 struct refcnt refcnt;
537 /** SCSI command-issuing interface */
538 struct interface control;
539 /** SCSI command interface */
540 struct interface data;
541 /** Transport-layer socket */
542 struct interface socket;
546 /** Target address */
547 char *target_address;
549 unsigned int target_port;
555 * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
560 /** Initiator username (if any) */
561 char *initiator_username;
562 /** Initiator password (if any) */
563 char *initiator_password;
564 /** Target username (if any) */
565 char *target_username;
566 /** Target password (if any) */
567 char *target_password;
568 /** CHAP challenge (for target auth only)
570 * This is a block of random data; the first byte is used as
571 * the CHAP identifier (CHAP_I) and the remainder as the CHAP
572 * challenge (CHAP_C).
574 unsigned char chap_challenge[17];
575 /** CHAP response (used for both initiator and target auth) */
576 struct chap_response chap;
578 /** Initiator session ID (IANA format) qualifier
580 * This is part of the ISID. It is generated randomly
581 * whenever a new connection is opened.
583 uint16_t isid_iana_qual;
584 /** Initiator task tag
586 * This is the tag of the current command. It is incremented
587 * whenever a new command is started.
590 /** Target transfer tag
592 * This is the tag attached to a sequence of data-out PDUs in
593 * response to an R2T.
598 * This is the offset for an in-progress sequence of data-out
599 * PDUs in response to an R2T.
601 uint32_t transfer_offset;
604 * This is the length for an in-progress sequence of data-out
605 * PDUs in response to an R2T.
607 uint32_t transfer_len;
608 /** Command sequence number
610 * This is the sequence number of the current command, used to
611 * fill out the CmdSN field in iSCSI request PDUs. It is
612 * updated with the value of the ExpCmdSN field whenever we
613 * receive an iSCSI response PDU containing such a field.
616 /** Status sequence number
618 * This is the most recent status sequence number present in
619 * the StatSN field of an iSCSI response PDU containing such a
620 * field. Whenever we send an iSCSI request PDU, we fill out
621 * the ExpStatSN field with this value plus one.
625 /** Basic header segment for current TX PDU */
626 union iscsi_bhs tx_bhs;
627 /** State of the TX engine */
628 enum iscsi_tx_state tx_state;
630 struct process process;
632 /** Basic header segment for current RX PDU */
633 union iscsi_bhs rx_bhs;
634 /** State of the RX engine */
635 enum iscsi_rx_state rx_state;
636 /** Byte offset within the current RX state */
638 /** Length of the current RX state */
640 /** Buffer for received data (not always used) */
643 /** Current SCSI command, if any */
644 struct scsi_cmd *command;
646 /** Target socket address (for boot firmware table) */
647 struct sockaddr target_sockaddr;
648 /** SCSI LUN (for boot firmware table) */
652 /** iSCSI session is currently in the security negotiation phase */
653 #define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
654 ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
655 ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
657 /** iSCSI session is currently in the operational parameter
660 #define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
661 ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
662 ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
664 /** iSCSI session is currently in the full feature phase */
665 #define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
667 /** Mask for all iSCSI session phases */
668 #define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
670 /** iSCSI session needs to send the initial security negotiation strings */
671 #define ISCSI_STATUS_STRINGS_SECURITY 0x0100
673 /** iSCSI session needs to send the CHAP_A string */
674 #define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
676 /** iSCSI session needs to send the CHAP response */
677 #define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
679 /** iSCSI session needs to send the mutual CHAP challenge */
680 #define ISCSI_STATUS_STRINGS_CHAP_CHALLENGE 0x0800
682 /** iSCSI session needs to send the operational negotiation strings */
683 #define ISCSI_STATUS_STRINGS_OPERATIONAL 0x1000
685 /** Mask for all iSCSI "needs to send" flags */
686 #define ISCSI_STATUS_STRINGS_MASK 0xff00
688 /** Target has requested forward (initiator) authentication */
689 #define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
691 /** Initiator requires target (reverse) authentication */
692 #define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
694 /** Target authenticated itself correctly */
695 #define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
697 /** Default initiator IQN prefix */
698 #define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe"
700 #endif /* _IPXE_ISCSI_H */