source: grub-pc/trunk/fuentes/debian/grub-extras/disabled/gpxe/src/include/gpxe/iscsi.h @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 17.0 KB
Line 
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 */
Note: See TracBrowser for help on using the repository browser.