1#ifndef _GPXE_ISCSI_H
2#define _GPXE_ISCSI_H
3
4/** @file
5 *
6 * iSCSI protocol
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER );
11
12#include <stdint.h>
13#include <gpxe/socket.h>
14#include <gpxe/scsi.h>
15#include <gpxe/chap.h>
16#include <gpxe/refcnt.h>
17#include <gpxe/xfer.h>
18#include <gpxe/process.h>
19
20/** Default iSCSI port */
21#define ISCSI_PORT 3260
22
23/**
24 * iSCSI segment lengths
25 *
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.
29 */
30union iscsi_segment_lengths {
31	struct {
32		/** The AHS length (measured in dwords) */
33		uint8_t ahs_len;
34		/** The data length (measured in bytes), in network
35		 * byte order
36		 */
37		uint8_t data_len[3];
38	} bytes;
39	/** Ths data length (measured in bytes), in network byte
40	 * order, with ahs_len as the first byte.
41	 */
42	uint32_t ahs_and_data_len;
43};
44
45/** The length of the additional header segment, in dwords */
46#define ISCSI_AHS_LEN( segment_lengths ) \
47	( (segment_lengths).bytes.ahs_len )
48
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 )
52
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 )
56
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 ) );			\
61	} while ( 0 )
62
63/**
64 * iSCSI basic header segment common fields
65 *
66 */
67struct iscsi_bhs_common {
68	/** Opcode */
69	uint8_t opcode;
70	/** Flags */
71	uint8_t flags;
72	/** Fields specific to the PDU type */
73	uint8_t other_a[2];
74	/** Segment lengths */
75	union iscsi_segment_lengths lengths;
76	/** Fields specific to the PDU type */
77	uint8_t other_b[8];
78	/** Initiator Task Tag */
79	uint32_t itt;
80	/** Fields specific to the PDU type */
81	uint8_t other_c[28];
82};
83
84/** Opcode mask */
85#define ISCSI_OPCODE_MASK 0x3f
86
87/** Immediate delivery */
88#define ISCSI_FLAG_IMMEDIATE 0x40
89
90/** Final PDU of a sequence */
91#define ISCSI_FLAG_FINAL 0x80
92
93/**
94 * iSCSI basic header segment common request fields
95 *
96 */
97struct iscsi_bhs_common_response {
98	/** Opcode */
99	uint8_t opcode;
100	/** Flags */
101	uint8_t flags;
102	/** Fields specific to the PDU type */
103	uint8_t other_a[2];
104	/** Segment lengths */
105	union iscsi_segment_lengths lengths;
106	/** Fields specific to the PDU type */
107	uint8_t other_b[8];
108	/** Initiator Task Tag */
109	uint32_t itt;
110	/** Fields specific to the PDU type */
111	uint8_t other_c[4];
112	/** Status sequence number */
113	uint32_t statsn;
114	/** Expected command sequence number */
115	uint32_t expcmdsn;
116	/** Fields specific to the PDU type */
117	uint8_t other_d[16];
118};
119
120/**
121 * iSCSI login request basic header segment
122 *
123 */
124struct iscsi_bhs_login_request {
125	/** Opcode */
126	uint8_t opcode;
127	/** Flags */
128	uint8_t flags;
129	/** Maximum supported version number */
130	uint8_t version_max;
131	/** Minimum supported version number */
132	uint8_t version_min;
133	/** Segment lengths */
134	union iscsi_segment_lengths lengths;
135	/** Initiator session ID (IANA format) enterprise number and flags */
136	uint32_t isid_iana_en;
137	/** Initiator session ID (IANA format) qualifier */
138	uint16_t isid_iana_qual;
139	/** Target session identifying handle */
140	uint16_t tsih;
141	/** Initiator Task Tag */
142	uint32_t itt;
143	/** Connection ID */
144	uint16_t cid;
145	/** Reserved */
146	uint16_t reserved_a;
147	/** Command sequence number */
148	uint32_t cmdsn;
149	/** Expected status sequence number */
150	uint32_t expstatsn;
151	/** Reserved */
152	uint8_t reserved_b[16];
153};
154
155/** Login request opcode */
156#define ISCSI_OPCODE_LOGIN_REQUEST 0x03
157
158/** Willingness to transition to next stage */
159#define ISCSI_LOGIN_FLAG_TRANSITION 0x80
160
161/** Key=value pairs continued in subsequent request */
162#define ISCSI_LOGIN_FLAG_CONTINUE 0x40
163
164/* Current stage values and mask */
165#define ISCSI_LOGIN_CSG_MASK 0x0c
166#define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
167#define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
168#define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
169
170/* Next stage values and mask */
171#define ISCSI_LOGIN_NSG_MASK 0x03
172#define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
173#define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
174#define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
175
176/** ISID IANA format marker */
177#define ISCSI_ISID_IANA 0x40000000
178
179/** Fen Systems Ltd. IANA enterprise number
180 *
181 * Permission is hereby granted to use Fen Systems Ltd.'s IANA
182 * enterprise number with this iSCSI implementation.
183 */
184#define IANA_EN_FEN_SYSTEMS 10019
185
186/**
187 * iSCSI login response basic header segment
188 *
189 */
190struct iscsi_bhs_login_response {
191	/** Opcode */
192	uint8_t opcode;
193	/** Flags */
194	uint8_t flags;
195	/** Maximum supported version number */
196	uint8_t version_max;
197	/** Minimum supported version number */
198	uint8_t version_min;
199	/** Segment lengths */
200	union iscsi_segment_lengths lengths;
201	/** Initiator session ID (IANA format) enterprise number and flags */
202	uint32_t isid_iana_en;
203	/** Initiator session ID (IANA format) qualifier */
204	uint16_t isid_iana_qual;
205	/** Target session identifying handle */
206	uint16_t tsih;
207	/** Initiator Task Tag */
208	uint32_t itt;
209	/** Reserved */
210	uint32_t reserved_a;
211	/** Status sequence number */
212	uint32_t statsn;
213	/** Expected command sequence number */
214	uint32_t expcmdsn;
215	/** Maximum command sequence number */
216	uint32_t maxcmdsn;
217	/** Status class */
218	uint8_t status_class;
219	/** Status detail */
220	uint8_t status_detail;
221	/** Reserved */
222	uint8_t reserved_b[10];
223};
224
225/** Login response opcode */
226#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
227
228/* Login response status codes */
229#define ISCSI_STATUS_SUCCESS			0x00
230#define ISCSI_STATUS_REDIRECT			0x01
231#define ISCSI_STATUS_INITIATOR_ERROR		0x02
232#define ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION	0x01
233#define ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION	0x02
234#define ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND		0x03
235#define ISCSI_STATUS_INITIATOR_ERROR_REMOVED		0x04
236#define ISCSI_STATUS_TARGET_ERROR		0x03
237
238/**
239 * iSCSI SCSI command basic header segment
240 *
241 */
242struct iscsi_bhs_scsi_command {
243	/** Opcode */
244	uint8_t opcode;
245	/** Flags */
246	uint8_t flags;
247	/** Reserved */
248	uint16_t reserved_a;
249	/** Segment lengths */
250	union iscsi_segment_lengths lengths;
251	/** SCSI Logical Unit Number */
252	struct scsi_lun lun;
253	/** Initiator Task Tag */
254	uint32_t itt;
255	/** Expected data transfer length */
256	uint32_t exp_len;
257	/** Command sequence number */
258	uint32_t cmdsn;
259	/** Expected status sequence number */
260	uint32_t expstatsn;
261	/** SCSI Command Descriptor Block (CDB) */
262	union scsi_cdb cdb;
263};
264
265/** SCSI command opcode */
266#define ISCSI_OPCODE_SCSI_COMMAND 0x01
267
268/** Command will read data */
269#define ISCSI_COMMAND_FLAG_READ 0x40
270
271/** Command will write data */
272#define ISCSI_COMMAND_FLAG_WRITE 0x20
273
274/* Task attributes */
275#define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
276#define ISCSI_COMMAND_ATTR_SIMPLE 0x01
277#define ISCSI_COMMAND_ATTR_ORDERED 0x02
278#define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
279#define ISCSI_COMMAND_ATTR_ACA 0x04
280
281/**
282 * iSCSI SCSI response basic header segment
283 *
284 */
285struct iscsi_bhs_scsi_response {
286	/** Opcode */
287	uint8_t opcode;
288	/** Flags */
289	uint8_t flags;
290	/** Response code */
291	uint8_t response;
292	/** SCSI status code */
293	uint8_t status;
294	/** Segment lengths */
295	union iscsi_segment_lengths lengths;
296	/** Reserved */
297	uint8_t reserved_a[8];
298	/** Initiator Task Tag */
299	uint32_t itt;
300	/** SNACK tag */
301	uint32_t snack;
302	/** Status sequence number */
303	uint32_t statsn;
304	/** Expected command sequence number */
305	uint32_t expcmdsn;
306	/** Maximum command sequence number */
307	uint32_t maxcmdsn;
308	/** Expected data sequence number */
309	uint32_t expdatasn;
310	/** Reserved */
311	uint8_t reserved_b[8];
312};
313
314/** SCSI response opcode */
315#define ISCSI_OPCODE_SCSI_RESPONSE 0x21
316
317/** SCSI command completed at target */
318#define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
319
320/** SCSI target failure */
321#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
322
323/** SCSI sense response code offset
324 *
325 * The SCSI response may contain unsolicited sense data in the data
326 * segment.  If it does, this is the offset to the sense response code
327 * byte, which is the only byte we care about.
328 */
329#define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
330
331/**
332 * iSCSI data-in basic header segment
333 *
334 */
335struct iscsi_bhs_data_in {
336	/** Opcode */
337	uint8_t opcode;
338	/** Flags */
339	uint8_t flags;
340	/** Reserved */
341	uint8_t reserved_a;
342	/** SCSI status code */
343	uint8_t status;
344	/** Segment lengths */
345	union iscsi_segment_lengths lengths;
346	/** Logical Unit Number */
347	struct scsi_lun lun;
348	/** Initiator Task Tag */
349	uint32_t itt;
350	/** Target Transfer Tag */
351	uint32_t ttt;
352	/** Status sequence number */
353	uint32_t statsn;
354	/** Expected command sequence number */
355	uint32_t expcmdsn;
356	/** Maximum command sequence number */
357	uint32_t maxcmdsn;
358	/** Data sequence number */
359	uint32_t datasn;
360	/** Buffer offset */
361	uint32_t offset;
362	/** Residual count */
363	uint32_t residual_count;
364};
365
366/** Data-in opcode */
367#define ISCSI_OPCODE_DATA_IN 0x25
368
369/** Data requires acknowledgement */
370#define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
371
372/** Data overflow occurred */
373#define ISCSI_DATA_FLAG_OVERFLOW 0x04
374
375/** Data underflow occurred */
376#define ISCSI_DATA_FLAG_UNDERFLOW 0x02
377
378/** SCSI status code and overflow/underflow flags are valid */
379#define ISCSI_DATA_FLAG_STATUS 0x01
380
381/**
382 * iSCSI data-out basic header segment
383 *
384 */
385struct iscsi_bhs_data_out {
386	/** Opcode */
387	uint8_t opcode;
388	/** Flags */
389	uint8_t flags;
390	/** Reserved */
391	uint16_t reserved_a;
392	/** Segment lengths */
393	union iscsi_segment_lengths lengths;
394	/** Logical Unit Number */
395	struct scsi_lun lun;
396	/** Initiator Task Tag */
397	uint32_t itt;
398	/** Target Transfer Tag */
399	uint32_t ttt;
400	/** Reserved */
401	uint32_t reserved_b;
402	/** Expected status sequence number */
403	uint32_t expstatsn;
404	/** Reserved */
405	uint32_t reserved_c;
406	/** Data sequence number */
407	uint32_t datasn;
408	/** Buffer offset */
409	uint32_t offset;
410	/** Reserved */
411	uint32_t reserved_d;
412};
413
414/** Data-out opcode */
415#define ISCSI_OPCODE_DATA_OUT 0x05
416
417/**
418 * iSCSI request to transfer basic header segment
419 *
420 */
421struct iscsi_bhs_r2t {
422	/** Opcode */
423	uint8_t opcode;
424	/** Flags */
425	uint8_t flags;
426	/** Reserved */
427	uint16_t reserved_a;
428	/** Segment lengths */
429	union iscsi_segment_lengths lengths;
430	/** Logical Unit Number */
431	struct scsi_lun lun;
432	/** Initiator Task Tag */
433	uint32_t itt;
434	/** Target Transfer Tag */
435	uint32_t ttt;
436	/** Status sequence number */
437	uint32_t statsn;
438	/** Expected command sequence number */
439	uint32_t expcmdsn;
440	/** Maximum command sequence number */
441	uint32_t maxcmdsn;
442	/** R2T sequence number */
443	uint32_t r2tsn;
444	/** Buffer offset */
445	uint32_t offset;
446	/** Desired data transfer length */
447	uint32_t len;
448};
449
450/** R2T opcode */
451#define ISCSI_OPCODE_R2T 0x31
452
453/**
454 * An iSCSI basic header segment
455 */
456union iscsi_bhs {
457	struct iscsi_bhs_common common;
458	struct iscsi_bhs_common_response common_response;
459	struct iscsi_bhs_login_request login_request;
460	struct iscsi_bhs_login_response login_response;
461	struct iscsi_bhs_scsi_command scsi_command;
462	struct iscsi_bhs_scsi_response scsi_response;
463	struct iscsi_bhs_data_in data_in;
464	struct iscsi_bhs_data_out data_out;
465	struct iscsi_bhs_r2t r2t;
466	unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
467};
468
469/** State of an iSCSI TX engine */
470enum iscsi_tx_state {
471	/** Nothing to send */
472	ISCSI_TX_IDLE = 0,
473	/** Sending the basic header segment */
474	ISCSI_TX_BHS,
475	/** Sending the additional header segment */
476	ISCSI_TX_AHS,
477	/** Sending the data segment */
478	ISCSI_TX_DATA,
479	/** Sending the data segment padding */
480	ISCSI_TX_DATA_PADDING,
481};
482
483/** State of an iSCSI RX engine */
484enum iscsi_rx_state {
485	/** Receiving the basic header segment */
486	ISCSI_RX_BHS = 0,
487	/** Receiving the additional header segment */
488	ISCSI_RX_AHS,
489	/** Receiving the data segment */
490	ISCSI_RX_DATA,
491	/** Receiving the data segment padding */
492	ISCSI_RX_DATA_PADDING,
493};
494
495/** An iSCSI session */
496struct iscsi_session {
497	/** Reference counter */
498	struct refcnt refcnt;
499
500	/** Transport-layer socket */
501	struct xfer_interface socket;
502
503	/** Target address */
504	char *target_address;
505	/** Target port */
506	unsigned int target_port;
507	/** Target IQN */
508	char *target_iqn;
509	/** Logical Unit Number (LUN) */
510	struct scsi_lun lun;
511	/** Target socket address (recorded only for iBFT) */
512	struct sockaddr target_sockaddr;
513
514	/** Session status
515	 *
516	 * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
517	 * constants.
518	 */
519	int status;
520	/** Retry count
521	 *
522	 * Number of times that the connection has been retried.
523	 * Reset upon a successful connection.
524	 */
525	int retry_count;
526
527	/** Initiator username (if any) */
528	char *initiator_username;
529	/** Initiator password (if any) */
530	char *initiator_password;
531	/** Target username (if any) */
532	char *target_username;
533	/** Target password (if any) */
534	char *target_password;
535	/** CHAP challenge (for target auth only)
536	 *
537	 * This is a block of random data; the first byte is used as
538	 * the CHAP identifier (CHAP_I) and the remainder as the CHAP
539	 * challenge (CHAP_C).
540	 */
541	unsigned char chap_challenge[17];
542	/** CHAP response (used for both initiator and target auth) */
543	struct chap_response chap;
544
545	/** Target session identifying handle
546	 *
547	 * This is assigned by the target when we first log in, and
548	 * must be reused on subsequent login attempts.
549	 */
550	uint16_t tsih;
551	/** Initiator task tag
552	 *
553	 * This is the tag of the current command.  It is incremented
554	 * whenever a new command is started.
555	 */
556	uint32_t itt;
557	/** Target transfer tag
558	 *
559	 * This is the tag attached to a sequence of data-out PDUs in
560	 * response to an R2T.
561	 */
562	uint32_t ttt;
563	/**
564	 * Transfer offset
565	 *
566	 * This is the offset for an in-progress sequence of data-out
567	 * PDUs in response to an R2T.
568	 */
569	uint32_t transfer_offset;
570	/**
571	 * Transfer length
572	 *
573	 * This is the length for an in-progress sequence of data-out
574	 * PDUs in response to an R2T.
575	 */
576	uint32_t transfer_len;
577	/** Command sequence number
578	 *
579	 * This is the sequence number of the current command, used to
580	 * fill out the CmdSN field in iSCSI request PDUs.  It is
581	 * updated with the value of the ExpCmdSN field whenever we
582	 * receive an iSCSI response PDU containing such a field.
583	 */
584	uint32_t cmdsn;
585	/** Status sequence number
586	 *
587	 * This is the most recent status sequence number present in
588	 * the StatSN field of an iSCSI response PDU containing such a
589	 * field.  Whenever we send an iSCSI request PDU, we fill out
590	 * the ExpStatSN field with this value plus one.
591	 */
592	uint32_t statsn;
593
594	/** Basic header segment for current TX PDU */
595	union iscsi_bhs tx_bhs;
596	/** State of the TX engine */
597	enum iscsi_tx_state tx_state;
598	/** TX process */
599	struct process process;
600
601	/** Basic header segment for current RX PDU */
602	union iscsi_bhs rx_bhs;
603	/** State of the RX engine */
604	enum iscsi_rx_state rx_state;
605	/** Byte offset within the current RX state */
606	size_t rx_offset;
607	/** Length of the current RX state */
608	size_t rx_len;
609	/** Buffer for received data (not always used) */
610	void *rx_buffer;
611
612	/** Current SCSI command
613	 *
614	 * Set to NULL when command is complete.
615	 */
616	struct scsi_command *command;
617	/** Instant return code
618	 *
619	 * Set to a non-zero value if all requests should return
620	 * immediately.  This can be used to e.g. avoid retrying
621	 * logins that are doomed to fail authentication.
622	 */
623	int instant_rc;
624};
625
626/** iSCSI session is currently in the security negotiation phase */
627#define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE		\
628	( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION |	\
629	  ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
630
631/** iSCSI session is currently in the operational parameter
632 * negotiation phase
633 */
634#define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE	\
635	( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION |	\
636	  ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
637
638/** iSCSI session is currently in the full feature phase */
639#define ISCSI_STATUS_FULL_FEATURE_PHASE	ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
640
641/** Mask for all iSCSI session phases */
642#define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
643
644/** iSCSI session needs to send the initial security negotiation strings */
645#define ISCSI_STATUS_STRINGS_SECURITY 0x0100
646
647/** iSCSI session needs to send the CHAP_A string */
648#define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
649
650/** iSCSI session needs to send the CHAP response */
651#define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
652
653/** iSCSI session needs to send the mutual CHAP challenge */
654#define ISCSI_STATUS_STRINGS_CHAP_CHALLENGE 0x0800
655
656/** iSCSI session needs to send the operational negotiation strings */
657#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x1000
658
659/** Mask for all iSCSI "needs to send" flags */
660#define ISCSI_STATUS_STRINGS_MASK 0xff00
661
662/** Target has requested forward (initiator) authentication */
663#define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
664
665/** Initiator requires target (reverse) authentication */
666#define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
667
668/** Target authenticated itself correctly */
669#define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
670
671/** Maximum number of retries at connecting */
672#define ISCSI_MAX_RETRIES 2
673
674extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path );
675extern void iscsi_detach ( struct scsi_device *scsi );
676extern const char * iscsi_initiator_iqn ( void );
677
678#endif /* _GPXE_ISCSI_H */
679