fa9fb98e3b04e80715dda50d9b81af812ee5413e
[people/meteger/gpxe.git] / src / net / tcp / iscsi.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stddef.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <byteswap.h>
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/socket.h>
30 #include <gpxe/xfer.h>
31 #include <gpxe/open.h>
32 #include <gpxe/scsi.h>
33 #include <gpxe/process.h>
34 #include <gpxe/uaccess.h>
35 #include <gpxe/tcpip.h>
36 #include <gpxe/settings.h>
37 #include <gpxe/features.h>
38 #include <gpxe/base16.h>
39 #include <gpxe/iscsi.h>
40
41 /** @file
42  *
43  * iSCSI protocol
44  *
45  */
46
47 FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
48
49 /* Disambiguate the various error causes */
50 #define EACCES_INCORRECT_TARGET_USERNAME ( EACCES | EUNIQ_01 )
51 #define EACCES_INCORRECT_TARGET_PASSWORD ( EACCES | EUNIQ_02 )
52 #define ENOTSUP_INITIATOR_STATUS ( ENOTSUP | EUNIQ_01 )
53 #define ENOTSUP_OPCODE ( ENOTSUP | EUNIQ_02 )
54 #define ENOTSUP_DISCOVERY ( ENOTSUP | EUNIQ_03 )
55 #define EPERM_INITIATOR_AUTHENTICATION ( EPERM | EUNIQ_01 )
56 #define EPERM_INITIATOR_AUTHORISATION ( EPERM | EUNIQ_02 )
57 #define EPROTO_INVALID_CHAP_ALGORITHM ( EPROTO | EUNIQ_01 )
58 #define EPROTO_INVALID_CHAP_IDENTIFIER ( EPROTO | EUNIQ_02 )
59 #define EPROTO_INVALID_CHAP_CHALLENGE ( EPROTO | EUNIQ_03 )
60 #define EPROTO_INVALID_CHAP_RESPONSE ( EPROTO | EUNIQ_04 )
61
62 /** iSCSI initiator name (explicitly specified) */
63 static char *iscsi_explicit_initiator_iqn;
64
65 /** Default iSCSI initiator name (constructed from hostname) */
66 static char *iscsi_default_initiator_iqn;
67
68 /** iSCSI initiator username */
69 static char *iscsi_initiator_username;
70
71 /** iSCSI initiator password */
72 static char *iscsi_initiator_password;
73
74 /** iSCSI target username */
75 static char *iscsi_target_username;
76
77 /** iSCSI target password */
78 static char *iscsi_target_password;
79
80 static void iscsi_start_tx ( struct iscsi_session *iscsi );
81 static void iscsi_start_login ( struct iscsi_session *iscsi );
82 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
83                                    unsigned int datasn );
84
85 /**
86  * Finish receiving PDU data into buffer
87  *
88  * @v iscsi             iSCSI session
89  */
90 static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
91         free ( iscsi->rx_buffer );
92         iscsi->rx_buffer = NULL;
93 }
94
95 /**
96  * Free iSCSI session
97  *
98  * @v refcnt            Reference counter
99  */
100 static void iscsi_free ( struct refcnt *refcnt ) {
101         struct iscsi_session *iscsi =
102                 container_of ( refcnt, struct iscsi_session, refcnt );
103
104         free ( iscsi->target_address );
105         free ( iscsi->target_iqn );
106         free ( iscsi->initiator_username );
107         free ( iscsi->initiator_password );
108         free ( iscsi->target_username );
109         free ( iscsi->target_password );
110         chap_finish ( &iscsi->chap );
111         iscsi_rx_buffered_data_done ( iscsi );
112         free ( iscsi );
113 }
114
115 /**
116  * Open iSCSI transport-layer connection
117  *
118  * @v iscsi             iSCSI session
119  * @ret rc              Return status code
120  */
121 static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
122         struct sockaddr_tcpip target;
123         int rc;
124
125         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
126         assert ( iscsi->rx_state == ISCSI_RX_BHS );
127         assert ( iscsi->rx_offset == 0 );
128
129         /* Open socket */
130         memset ( &target, 0, sizeof ( target ) );
131         target.st_port = htons ( iscsi->target_port );
132         if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
133                                              ( struct sockaddr * ) &target,
134                                              iscsi->target_address,
135                                              NULL ) ) != 0 ) {
136                 DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
137                        iscsi, strerror ( rc ) );
138                 return rc;
139         }
140
141         /* Enter security negotiation phase */
142         iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
143                           ISCSI_STATUS_STRINGS_SECURITY );
144         if ( iscsi->target_username )
145                 iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
146
147         /* Assign fresh initiator task tag */
148         iscsi->itt++;
149
150         /* Initiate login */
151         iscsi_start_login ( iscsi );
152
153         return 0;
154 }
155
156 /**
157  * Close iSCSI transport-layer connection
158  *
159  * @v iscsi             iSCSI session
160  * @v rc                Reason for close
161  *
162  * Closes the transport-layer connection and resets the session state
163  * ready to attempt a fresh login.
164  */
165 static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
166
167         /* Close all data transfer interfaces */
168         xfer_close ( &iscsi->socket, rc );
169
170         /* Clear connection status */
171         iscsi->status = 0;
172
173         /* Reset TX and RX state machines */
174         iscsi->tx_state = ISCSI_TX_IDLE;
175         iscsi->rx_state = ISCSI_RX_BHS;
176         iscsi->rx_offset = 0;
177
178         /* Free any temporary dynamically allocated memory */
179         chap_finish ( &iscsi->chap );
180         iscsi_rx_buffered_data_done ( iscsi );
181 }
182
183 /**
184  * Mark iSCSI SCSI operation as complete
185  *
186  * @v iscsi             iSCSI session
187  * @v rc                Return status code
188  *
189  * Note that iscsi_scsi_done() will not close the connection, and must
190  * therefore be called only when the internal state machines are in an
191  * appropriate state, otherwise bad things may happen on the next call
192  * to iscsi_issue().  The general rule is to call iscsi_scsi_done()
193  * only at the end of receiving a PDU; at this point the TX and RX
194  * engines should both be idle.
195  */
196 static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
197
198         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
199         assert ( iscsi->command != NULL );
200
201         iscsi->command->rc = rc;
202         iscsi->command = NULL;
203 }
204
205 /****************************************************************************
206  *
207  * iSCSI SCSI command issuing
208  *
209  */
210
211 /**
212  * Build iSCSI SCSI command BHS
213  *
214  * @v iscsi             iSCSI session
215  *
216  * We don't currently support bidirectional commands (i.e. with both
217  * Data-In and Data-Out segments); these would require providing code
218  * to generate an AHS, and there doesn't seem to be any need for it at
219  * the moment.
220  */
221 static void iscsi_start_command ( struct iscsi_session *iscsi ) {
222         struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
223
224         assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
225
226         /* Construct BHS and initiate transmission */
227         iscsi_start_tx ( iscsi );
228         command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
229         command->flags = ( ISCSI_FLAG_FINAL |
230                            ISCSI_COMMAND_ATTR_SIMPLE );
231         if ( iscsi->command->data_in )
232                 command->flags |= ISCSI_COMMAND_FLAG_READ;
233         if ( iscsi->command->data_out )
234                 command->flags |= ISCSI_COMMAND_FLAG_WRITE;
235         /* lengths left as zero */
236         command->lun = iscsi->lun;
237         command->itt = htonl ( ++iscsi->itt );
238         command->exp_len = htonl ( iscsi->command->data_in_len |
239                                    iscsi->command->data_out_len );
240         command->cmdsn = htonl ( iscsi->cmdsn );
241         command->expstatsn = htonl ( iscsi->statsn + 1 );
242         memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
243         DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
244                 iscsi, SCSI_CDB_DATA ( command->cdb ),
245                 ( iscsi->command->data_in ? "in" : "out" ),
246                 ( iscsi->command->data_in ?
247                   iscsi->command->data_in_len :
248                   iscsi->command->data_out_len ) );
249 }
250
251 /**
252  * Receive data segment of an iSCSI SCSI response PDU
253  *
254  * @v iscsi             iSCSI session
255  * @v data              Received data
256  * @v len               Length of received data
257  * @v remaining         Data remaining after this data
258  * @ret rc              Return status code
259  */
260 static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
261                                     const void *data, size_t len,
262                                     size_t remaining ) {
263         struct iscsi_bhs_scsi_response *response
264                 = &iscsi->rx_bhs.scsi_response;
265         int sense_offset;
266
267         /* Capture the sense response code as it floats past, if present */
268         sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
269         if ( ( sense_offset >= 0 ) && len ) {
270                 iscsi->command->sense_response =
271                         * ( ( char * ) data + sense_offset );
272         }
273
274         /* Wait for whole SCSI response to arrive */
275         if ( remaining )
276                 return 0;
277         
278         /* Record SCSI status code */
279         iscsi->command->status = response->status;
280
281         /* Check for errors */
282         if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
283                 return -EIO;
284
285         /* Mark as completed */
286         iscsi_scsi_done ( iscsi, 0 );
287         return 0;
288 }
289
290 /**
291  * Receive data segment of an iSCSI data-in PDU
292  *
293  * @v iscsi             iSCSI session
294  * @v data              Received data
295  * @v len               Length of received data
296  * @v remaining         Data remaining after this data
297  * @ret rc              Return status code
298  */
299 static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
300                               const void *data, size_t len,
301                               size_t remaining ) {
302         struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
303         unsigned long offset;
304
305         /* Copy data to data-in buffer */
306         offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
307         assert ( iscsi->command != NULL );
308         assert ( iscsi->command->data_in );
309         assert ( ( offset + len ) <= iscsi->command->data_in_len );
310         copy_to_user ( iscsi->command->data_in, offset, data, len );
311
312         /* Wait for whole SCSI response to arrive */
313         if ( remaining )
314                 return 0;
315
316         /* Mark as completed if status is present */
317         if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
318                 assert ( ( offset + len ) == iscsi->command->data_in_len );
319                 assert ( data_in->flags & ISCSI_FLAG_FINAL );
320                 iscsi->command->status = data_in->status;
321                 /* iSCSI cannot return an error status via a data-in */
322                 iscsi_scsi_done ( iscsi, 0 );
323         }
324
325         return 0;
326 }
327
328 /**
329  * Receive data segment of an iSCSI R2T PDU
330  *
331  * @v iscsi             iSCSI session
332  * @v data              Received data
333  * @v len               Length of received data
334  * @v remaining         Data remaining after this data
335  * @ret rc              Return status code
336  */
337 static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
338                           const void *data __unused, size_t len __unused,
339                           size_t remaining __unused ) {
340         struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
341
342         /* Record transfer parameters and trigger first data-out */
343         iscsi->ttt = ntohl ( r2t->ttt );
344         iscsi->transfer_offset = ntohl ( r2t->offset );
345         iscsi->transfer_len = ntohl ( r2t->len );
346         iscsi_start_data_out ( iscsi, 0 );
347
348         return 0;
349 }
350
351 /**
352  * Build iSCSI data-out BHS
353  *
354  * @v iscsi             iSCSI session
355  * @v datasn            Data sequence number within the transfer
356  *
357  */
358 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
359                                    unsigned int datasn ) {
360         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
361         unsigned long offset;
362         unsigned long remaining;
363         unsigned long len;
364
365         /* We always send 512-byte Data-Out PDUs; this removes the
366          * need to worry about the target's MaxRecvDataSegmentLength.
367          */
368         offset = datasn * 512;
369         remaining = iscsi->transfer_len - offset;
370         len = remaining;
371         if ( len > 512 )
372                 len = 512;
373
374         /* Construct BHS and initiate transmission */
375         iscsi_start_tx ( iscsi );
376         data_out->opcode = ISCSI_OPCODE_DATA_OUT;
377         if ( len == remaining )
378                 data_out->flags = ( ISCSI_FLAG_FINAL );
379         ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
380         data_out->lun = iscsi->lun;
381         data_out->itt = htonl ( iscsi->itt );
382         data_out->ttt = htonl ( iscsi->ttt );
383         data_out->expstatsn = htonl ( iscsi->statsn + 1 );
384         data_out->datasn = htonl ( datasn );
385         data_out->offset = htonl ( iscsi->transfer_offset + offset );
386         DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
387                iscsi, datasn, len );
388 }
389
390 /**
391  * Complete iSCSI data-out PDU transmission
392  *
393  * @v iscsi             iSCSI session
394  *
395  */
396 static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
397         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
398
399         /* If we haven't reached the end of the sequence, start
400          * sending the next data-out PDU.
401          */
402         if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
403                 iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
404 }
405
406 /**
407  * Send iSCSI data-out data segment
408  *
409  * @v iscsi             iSCSI session
410  * @ret rc              Return status code
411  */
412 static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
413         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
414         struct io_buffer *iobuf;
415         unsigned long offset;
416         size_t len;
417
418         offset = ntohl ( data_out->offset );
419         len = ISCSI_DATA_LEN ( data_out->lengths );
420
421         assert ( iscsi->command != NULL );
422         assert ( iscsi->command->data_out );
423         assert ( ( offset + len ) <= iscsi->command->data_out_len );
424
425         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
426         if ( ! iobuf )
427                 return -ENOMEM;
428         
429         copy_from_user ( iob_put ( iobuf, len ),
430                          iscsi->command->data_out, offset, len );
431
432         return xfer_deliver_iob ( &iscsi->socket, iobuf );
433 }
434
435 /****************************************************************************
436  *
437  * iSCSI login
438  *
439  */
440
441 /**
442  * Build iSCSI login request strings
443  *
444  * @v iscsi             iSCSI session
445  *
446  * These are the initial set of strings sent in the first login
447  * request PDU.  We want the following settings:
448  *
449  *     HeaderDigest=None
450  *     DataDigest=None
451  *     MaxConnections is irrelevant; we make only one connection anyway [4]
452  *     InitialR2T=Yes [1]
453  *     ImmediateData is irrelevant; we never send immediate data [4]
454  *     MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
455  *     MaxBurstLength=262144 (default; we don't care) [3]
456  *     FirstBurstLength=262144 (default; we don't care)
457  *     DefaultTime2Wait=0 [2]
458  *     DefaultTime2Retain=0 [2]
459  *     MaxOutstandingR2T=1
460  *     DataPDUInOrder=Yes
461  *     DataSequenceInOrder=Yes
462  *     ErrorRecoveryLevel=0
463  *
464  * [1] InitialR2T has an OR resolution function, so the target may
465  * force us to use it.  We therefore simplify our logic by always
466  * using it.
467  *
468  * [2] These ensure that we can safely start a new task once we have
469  * reconnected after a failure, without having to manually tidy up
470  * after the old one.
471  *
472  * [3] We are quite happy to use the RFC-defined default values for
473  * these parameters, but some targets (notably OpenSolaris)
474  * incorrectly assume a default value of zero, so we explicitly
475  * specify the default values.
476  *
477  * [4] We are quite happy to use the RFC-defined default values for
478  * these parameters, but some targets (notably a QNAP TS-639Pro) fail
479  * unless they are supplied, so we explicitly specify the default
480  * values.
481  */
482 static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
483                                                void *data, size_t len ) {
484         unsigned int used = 0;
485         const char *auth_method;
486
487         if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
488                 /* Default to allowing no authentication */
489                 auth_method = "None";
490                 /* If we have a credential to supply, permit CHAP */
491                 if ( iscsi->initiator_username )
492                         auth_method = "CHAP,None";
493                 /* If we have a credential to check, force CHAP */
494                 if ( iscsi->target_username )
495                         auth_method = "CHAP";
496                 used += ssnprintf ( data + used, len - used,
497                                     "InitiatorName=%s%c"
498                                     "TargetName=%s%c"
499                                     "SessionType=Normal%c"
500                                     "AuthMethod=%s%c",
501                                     iscsi_initiator_iqn(), 0,
502                                     iscsi->target_iqn, 0, 0,
503                                     auth_method, 0 );
504         }
505
506         if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
507                 used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
508         }
509         
510         if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
511                 char buf[ base16_encoded_len ( iscsi->chap.response_len ) + 1 ];
512                 assert ( iscsi->initiator_username != NULL );
513                 base16_encode ( iscsi->chap.response, iscsi->chap.response_len,
514                                 buf );
515                 used += ssnprintf ( data + used, len - used,
516                                     "CHAP_N=%s%cCHAP_R=0x%s%c",
517                                     iscsi->initiator_username, 0, buf, 0 );
518         }
519
520         if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
521                 size_t challenge_len = ( sizeof ( iscsi->chap_challenge ) - 1 );
522                 char buf[ base16_encoded_len ( challenge_len ) + 1 ];
523                 base16_encode ( ( iscsi->chap_challenge + 1 ), challenge_len,
524                                 buf );
525                 used += ssnprintf ( data + used, len - used,
526                                     "CHAP_I=%d%cCHAP_C=0x%s%c",
527                                     iscsi->chap_challenge[0], 0, buf, 0 );
528         }
529
530         if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
531                 used += ssnprintf ( data + used, len - used,
532                                     "HeaderDigest=None%c"
533                                     "DataDigest=None%c"
534                                     "MaxConnections=1%c"
535                                     "InitialR2T=Yes%c"
536                                     "ImmediateData=No%c"
537                                     "MaxRecvDataSegmentLength=8192%c"
538                                     "MaxBurstLength=262144%c"
539                                     "DefaultTime2Wait=0%c"
540                                     "DefaultTime2Retain=0%c"
541                                     "MaxOutstandingR2T=1%c"
542                                     "DataPDUInOrder=Yes%c"
543                                     "DataSequenceInOrder=Yes%c"
544                                     "ErrorRecoveryLevel=0%c",
545                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
546         }
547
548         return used;
549 }
550
551 /**
552  * Build iSCSI login request BHS
553  *
554  * @v iscsi             iSCSI session
555  */
556 static void iscsi_start_login ( struct iscsi_session *iscsi ) {
557         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
558         int len;
559
560         /* Construct BHS and initiate transmission */
561         iscsi_start_tx ( iscsi );
562         request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
563                             ISCSI_FLAG_IMMEDIATE );
564         request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
565                            ISCSI_LOGIN_FLAG_TRANSITION );
566         /* version_max and version_min left as zero */
567         len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
568         ISCSI_SET_LENGTHS ( request->lengths, 0, len );
569         request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
570                                         IANA_EN_FEN_SYSTEMS );
571         /* isid_iana_qual left as zero */
572         request->tsih = htons ( iscsi->tsih );
573         request->itt = htonl ( iscsi->itt );
574         /* cid left as zero */
575         request->cmdsn = htonl ( iscsi->cmdsn );
576         request->expstatsn = htonl ( iscsi->statsn + 1 );
577 }
578
579 /**
580  * Complete iSCSI login request PDU transmission
581  *
582  * @v iscsi             iSCSI session
583  *
584  */
585 static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
586
587         /* Clear any "strings to send" flags */
588         iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
589
590         /* Free any dynamically allocated storage used for login */
591         chap_finish ( &iscsi->chap );
592 }
593
594 /**
595  * Transmit data segment of an iSCSI login request PDU
596  *
597  * @v iscsi             iSCSI session
598  * @ret rc              Return status code
599  *
600  * For login requests, the data segment consists of the login strings.
601  */
602 static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
603         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
604         struct io_buffer *iobuf;
605         size_t len;
606
607         len = ISCSI_DATA_LEN ( request->lengths );
608         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
609         if ( ! iobuf )
610                 return -ENOMEM;
611         iob_put ( iobuf, len );
612         iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
613         return xfer_deliver_iob ( &iscsi->socket, iobuf );
614 }
615
616 /**
617  * Handle iSCSI TargetAddress text value
618  *
619  * @v iscsi             iSCSI session
620  * @v value             TargetAddress value
621  * @ret rc              Return status code
622  */
623 static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
624                                               const char *value ) {
625         char *separator;
626
627         DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
628
629         /* Replace target address */
630         free ( iscsi->target_address );
631         iscsi->target_address = strdup ( value );
632         if ( ! iscsi->target_address )
633                 return -ENOMEM;
634
635         /* Replace target port */
636         iscsi->target_port = htons ( ISCSI_PORT );
637         separator = strchr ( iscsi->target_address, ':' );
638         if ( separator ) {
639                 *separator = '\0';
640                 iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
641         }
642
643         return 0;
644 }
645
646 /**
647  * Handle iSCSI AuthMethod text value
648  *
649  * @v iscsi             iSCSI session
650  * @v value             AuthMethod value
651  * @ret rc              Return status code
652  */
653 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
654                                            const char *value ) {
655
656         /* If server requests CHAP, send the CHAP_A string */
657         if ( strcmp ( value, "CHAP" ) == 0 ) {
658                 DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
659                        iscsi );
660                 iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
661                                    ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
662         }
663
664         return 0;
665 }
666
667 /**
668  * Handle iSCSI CHAP_A text value
669  *
670  * @v iscsi             iSCSI session
671  * @v value             CHAP_A value
672  * @ret rc              Return status code
673  */
674 static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
675                                        const char *value ) {
676
677         /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
678          * the server responds with anything else it is a protocol
679          * violation.
680          */
681         if ( strcmp ( value, "5" ) != 0 ) {
682                 DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
683                        iscsi, value );
684                 return -EPROTO_INVALID_CHAP_ALGORITHM;
685         }
686
687         return 0;
688 }
689
690 /**
691  * Handle iSCSI CHAP_I text value
692  *
693  * @v iscsi             iSCSI session
694  * @v value             CHAP_I value
695  * @ret rc              Return status code
696  */
697 static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
698                                        const char *value ) {
699         unsigned int identifier;
700         char *endp;
701         int rc;
702
703         /* The CHAP identifier is an integer value */
704         identifier = strtoul ( value, &endp, 0 );
705         if ( *endp != '\0' ) {
706                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
707                        iscsi, value );
708                 return -EPROTO_INVALID_CHAP_IDENTIFIER;
709         }
710
711         /* Prepare for CHAP with MD5 */
712         chap_finish ( &iscsi->chap );
713         if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
714                 DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
715                        iscsi, strerror ( rc ) );
716                 return rc;
717         }
718
719         /* Identifier and secret are the first two components of the
720          * challenge.
721          */
722         chap_set_identifier ( &iscsi->chap, identifier );
723         if ( iscsi->initiator_password ) {
724                 chap_update ( &iscsi->chap, iscsi->initiator_password,
725                               strlen ( iscsi->initiator_password ) );
726         }
727
728         return 0;
729 }
730
731 /**
732  * Handle iSCSI CHAP_C text value
733  *
734  * @v iscsi             iSCSI session
735  * @v value             CHAP_C value
736  * @ret rc              Return status code
737  */
738 static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
739                                        const char *value ) {
740         uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */
741         unsigned int i;
742         int len;
743
744         /* Check and strip leading "0x" */
745         if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
746                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
747                        iscsi, value );
748                 return -EPROTO_INVALID_CHAP_CHALLENGE;
749         }
750
751         /* Process challenge */
752         len = base16_decode ( ( value + 2 ), buf );
753         if ( len < 0 ) {
754                 DBGC ( iscsi, "iSCSI %p invalid CHAP challenge \"%s\": %s\n",
755                        iscsi, value, strerror ( len ) );
756                 return len;
757         }
758         chap_update ( &iscsi->chap, buf, len );
759
760         /* Build CHAP response */
761         DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
762         chap_respond ( &iscsi->chap );
763         iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
764
765         /* Send CHAP challenge, if applicable */
766         if ( iscsi->target_username ) {
767                 iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
768                 /* Generate CHAP challenge data */
769                 for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
770                         iscsi->chap_challenge[i] = random();
771                 }
772         }
773
774         return 0;
775 }
776
777 /**
778  * Handle iSCSI CHAP_N text value
779  *
780  * @v iscsi             iSCSI session
781  * @v value             CHAP_N value
782  * @ret rc              Return status code
783  */
784 static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
785                                        const char *value ) {
786
787         /* The target username isn't actually involved at any point in
788          * the authentication process; it merely serves to identify
789          * which password the target is using to generate the CHAP
790          * response.  We unnecessarily verify that the username is as
791          * expected, in order to provide mildly helpful diagnostics if
792          * the target is supplying the wrong username/password
793          * combination.
794          */
795         if ( iscsi->target_username &&
796              ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
797                 DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
798                        "(wanted \"%s\")\n",
799                        iscsi, value, iscsi->target_username );
800                 return -EACCES_INCORRECT_TARGET_USERNAME;
801         }
802
803         return 0;
804 }
805
806 /**
807  * Handle iSCSI CHAP_R text value
808  *
809  * @v iscsi             iSCSI session
810  * @v value             CHAP_R value
811  * @ret rc              Return status code
812  */
813 static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
814                                        const char *value ) {
815         uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */
816         size_t len;
817         int rc;
818
819         /* Generate CHAP response for verification */
820         chap_finish ( &iscsi->chap );
821         if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
822                 DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
823                        iscsi, strerror ( rc ) );
824                 return rc;
825         }
826         chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
827         if ( iscsi->target_password ) {
828                 chap_update ( &iscsi->chap, iscsi->target_password,
829                               strlen ( iscsi->target_password ) );
830         }
831         chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
832                       ( sizeof ( iscsi->chap_challenge ) - 1 ) );
833         chap_respond ( &iscsi->chap );
834
835         /* Check and strip leading "0x" */
836         if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
837                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
838                        iscsi, value );
839                 return -EPROTO_INVALID_CHAP_RESPONSE;
840         }
841
842         /* Process response */
843         rc = base16_decode ( ( value + 2 ), buf );
844         if ( rc < 0 ) {
845                 DBGC ( iscsi, "iSCSI %p invalid CHAP response \"%s\": %s\n",
846                        iscsi, value, strerror ( rc ) );
847                 return rc;
848         }
849         len = rc;
850
851         /* Check CHAP response */
852         if ( len != iscsi->chap.response_len ) {
853                 DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
854                        iscsi );
855                 return -EPROTO_INVALID_CHAP_RESPONSE;
856         }
857         if ( memcmp ( buf, iscsi->chap.response, len ) != 0 ) {
858                 DBGC ( iscsi, "iSCSI %p incorrect CHAP response \"%s\"\n",
859                        iscsi, value );
860                 return -EACCES_INCORRECT_TARGET_PASSWORD;
861         }
862
863         /* Mark session as authenticated */
864         iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
865
866         return 0;
867 }
868
869 /** An iSCSI text string that we want to handle */
870 struct iscsi_string_type {
871         /** String key
872          *
873          * This is the portion up to and including the "=" sign,
874          * e.g. "InitiatorName=", "CHAP_A=", etc.
875          */
876         const char *key;
877         /** Handle iSCSI string value
878          *
879          * @v iscsi             iSCSI session
880          * @v value             iSCSI string value
881          * @ret rc              Return status code
882          */
883         int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
884 };
885
886 /** iSCSI text strings that we want to handle */
887 static struct iscsi_string_type iscsi_string_types[] = {
888         { "TargetAddress=", iscsi_handle_targetaddress_value },
889         { "AuthMethod=", iscsi_handle_authmethod_value },
890         { "CHAP_A=", iscsi_handle_chap_a_value },
891         { "CHAP_I=", iscsi_handle_chap_i_value },
892         { "CHAP_C=", iscsi_handle_chap_c_value },
893         { "CHAP_N=", iscsi_handle_chap_n_value },
894         { "CHAP_R=", iscsi_handle_chap_r_value },
895         { NULL, NULL }
896 };
897
898 /**
899  * Handle iSCSI string
900  *
901  * @v iscsi             iSCSI session
902  * @v string            iSCSI string (in "key=value" format)
903  * @ret rc              Return status code
904  */
905 static int iscsi_handle_string ( struct iscsi_session *iscsi,
906                                  const char *string ) {
907         struct iscsi_string_type *type;
908         size_t key_len;
909         int rc;
910
911         for ( type = iscsi_string_types ; type->key ; type++ ) {
912                 key_len = strlen ( type->key );
913                 if ( strncmp ( string, type->key, key_len ) != 0 )
914                         continue;
915                 DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
916                 if ( ( rc = type->handle ( iscsi,
917                                            ( string + key_len ) ) ) != 0 ) {
918                         DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
919                                iscsi, string, strerror ( rc ) );
920                         return rc;
921                 }
922                 return 0;
923         }
924         DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
925         return 0;
926 }
927
928 /**
929  * Handle iSCSI strings
930  *
931  * @v iscsi             iSCSI session
932  * @v string            iSCSI string buffer
933  * @v len               Length of string buffer
934  * @ret rc              Return status code
935  */
936 static int iscsi_handle_strings ( struct iscsi_session *iscsi,
937                                   const char *strings, size_t len ) {
938         size_t string_len;
939         int rc;
940
941         /* Handle each string in turn, taking care not to overrun the
942          * data buffer in case of badly-terminated data.
943          */
944         while ( 1 ) {
945                 string_len = ( strnlen ( strings, len ) + 1 );
946                 if ( string_len > len )
947                         break;
948                 if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
949                         return rc;
950                 strings += string_len;
951                 len -= string_len;
952         }
953         return 0;
954 }
955
956 /**
957  * Receive PDU data into buffer
958  *
959  * @v iscsi             iSCSI session
960  * @v data              Data to receive
961  * @v len               Length of data
962  * @ret rc              Return status code
963  *
964  * This can be used when the RX PDU type handler wishes to buffer up
965  * all received data and process the PDU as a single unit.  The caller
966  * is repsonsible for calling iscsi_rx_buffered_data_done() after
967  * processing the data.
968  */
969 static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
970                                     const void *data, size_t len ) {
971
972         /* Allocate buffer on first call */
973         if ( ! iscsi->rx_buffer ) {
974                 iscsi->rx_buffer = malloc ( iscsi->rx_len );
975                 if ( ! iscsi->rx_buffer )
976                         return -ENOMEM;
977         }
978
979         /* Copy data to buffer */
980         assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
981         memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
982
983         return 0;
984 }
985
986 /**
987  * Convert iSCSI response status to return status code
988  *
989  * @v status_class      iSCSI status class
990  * @v status_detail     iSCSI status detail
991  * @ret rc              Return status code
992  */
993 static int iscsi_status_to_rc ( unsigned int status_class,
994                                 unsigned int status_detail ) {
995         switch ( status_class ) {
996         case ISCSI_STATUS_INITIATOR_ERROR :
997                 switch ( status_detail ) {
998                 case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
999                         return -EPERM_INITIATOR_AUTHENTICATION;
1000                 case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
1001                         return -EPERM_INITIATOR_AUTHORISATION;
1002                 case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
1003                 case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
1004                         return -ENODEV;
1005                 default :
1006                         return -ENOTSUP_INITIATOR_STATUS;
1007                 }
1008         case ISCSI_STATUS_TARGET_ERROR :
1009                 return -EIO;
1010         default :
1011                 return -EINVAL;
1012         }
1013 }
1014
1015 /**
1016  * Receive data segment of an iSCSI login response PDU
1017  *
1018  * @v iscsi             iSCSI session
1019  * @v data              Received data
1020  * @v len               Length of received data
1021  * @v remaining         Data remaining after this data
1022  * @ret rc              Return status code
1023  */
1024 static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
1025                                      const void *data, size_t len,
1026                                      size_t remaining ) {
1027         struct iscsi_bhs_login_response *response
1028                 = &iscsi->rx_bhs.login_response;
1029         int rc;
1030
1031         /* Buffer up the PDU data */
1032         if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
1033                 DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
1034                        iscsi, strerror ( rc ) );
1035                 return rc;
1036         }
1037         if ( remaining )
1038                 return 0;
1039
1040         /* Process string data and discard string buffer */
1041         if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
1042                                            iscsi->rx_len ) ) != 0 )
1043                 return rc;
1044         iscsi_rx_buffered_data_done ( iscsi );
1045
1046         /* Check for login redirection */
1047         if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
1048                 DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
1049                 iscsi_close_connection ( iscsi, 0 );
1050                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1051                         DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
1052                                iscsi, strerror ( rc ) );
1053                         return rc;
1054                 }
1055                 return 0;
1056         }
1057
1058         /* Check for fatal errors */
1059         if ( response->status_class != 0 ) {
1060                 DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
1061                        response->status_class, response->status_detail );
1062                 rc = iscsi_status_to_rc ( response->status_class,
1063                                           response->status_detail );
1064                 iscsi->instant_rc = rc;
1065                 return rc;
1066         }
1067
1068         /* Handle login transitions */
1069         if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
1070                 iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
1071                                     ISCSI_STATUS_STRINGS_MASK );
1072                 switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
1073                 case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
1074                         iscsi->status |=
1075                                 ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
1076                                   ISCSI_STATUS_STRINGS_OPERATIONAL );
1077                         break;
1078                 case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
1079                         iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
1080                         break;
1081                 default:
1082                         DBGC ( iscsi, "iSCSI %p got invalid response flags "
1083                                "%02x\n", iscsi, response->flags );
1084                         return -EIO;
1085                 }
1086         }
1087
1088         /* Send next login request PDU if we haven't reached the full
1089          * feature phase yet.
1090          */
1091         if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
1092              ISCSI_STATUS_FULL_FEATURE_PHASE ) {
1093                 iscsi_start_login ( iscsi );
1094                 return 0;
1095         }
1096
1097         /* Check that target authentication was successful (if required) */
1098         if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
1099              ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
1100                 DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
1101                        "authentication\n", iscsi );
1102                 return -EPROTO;
1103         }
1104
1105         /* Reset retry count */
1106         iscsi->retry_count = 0;
1107
1108         /* Record TSIH for future reference */
1109         iscsi->tsih = ntohl ( response->tsih );
1110         
1111         /* Send the actual SCSI command */
1112         iscsi_start_command ( iscsi );
1113
1114         return 0;
1115 }
1116
1117 /****************************************************************************
1118  *
1119  * iSCSI to socket interface
1120  *
1121  */
1122
1123 /**
1124  * Start up a new TX PDU
1125  *
1126  * @v iscsi             iSCSI session
1127  *
1128  * This initiates the process of sending a new PDU.  Only one PDU may
1129  * be in transit at any one time.
1130  */
1131 static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
1132         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
1133         
1134         /* Initialise TX BHS */
1135         memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
1136
1137         /* Flag TX engine to start transmitting */
1138         iscsi->tx_state = ISCSI_TX_BHS;
1139 }
1140
1141 /**
1142  * Transmit nothing
1143  *
1144  * @v iscsi             iSCSI session
1145  * @ret rc              Return status code
1146  */
1147 static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
1148         return 0;
1149 }
1150
1151 /**
1152  * Transmit basic header segment of an iSCSI PDU
1153  *
1154  * @v iscsi             iSCSI session
1155  * @ret rc              Return status code
1156  */
1157 static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
1158         return xfer_deliver_raw ( &iscsi->socket,  &iscsi->tx_bhs,
1159                                   sizeof ( iscsi->tx_bhs ) );
1160 }
1161
1162 /**
1163  * Transmit data segment of an iSCSI PDU
1164  *
1165  * @v iscsi             iSCSI session
1166  * @ret rc              Return status code
1167  * 
1168  * Handle transmission of part of a PDU data segment.  iscsi::tx_bhs
1169  * will be valid when this is called.
1170  */
1171 static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
1172         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1173
1174         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
1175         case ISCSI_OPCODE_DATA_OUT:
1176                 return iscsi_tx_data_out ( iscsi );
1177         case ISCSI_OPCODE_LOGIN_REQUEST:
1178                 return iscsi_tx_login_request ( iscsi );
1179         default:
1180                 /* Nothing to send in other states */
1181                 return 0;
1182         }
1183 }
1184
1185 /**
1186  * Transmit data padding of an iSCSI PDU
1187  *
1188  * @v iscsi             iSCSI session
1189  * @ret rc              Return status code
1190  * 
1191  * Handle transmission of any data padding in a PDU data segment.
1192  * iscsi::tx_bhs will be valid when this is called.
1193  */
1194 static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
1195         static const char pad[] = { '\0', '\0', '\0' };
1196         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1197         size_t pad_len;
1198         
1199         pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1200         if ( ! pad_len )
1201                 return 0;
1202
1203         return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
1204 }
1205
1206 /**
1207  * Complete iSCSI PDU transmission
1208  *
1209  * @v iscsi             iSCSI session
1210  *
1211  * Called when a PDU has been completely transmitted and the TX state
1212  * machine is about to enter the idle state.  iscsi::tx_bhs will be
1213  * valid for the just-completed PDU when this is called.
1214  */
1215 static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
1216         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1217
1218         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
1219         case ISCSI_OPCODE_DATA_OUT:
1220                 iscsi_data_out_done ( iscsi );
1221         case ISCSI_OPCODE_LOGIN_REQUEST:
1222                 iscsi_login_request_done ( iscsi );
1223         default:
1224                 /* No action */
1225                 break;
1226         }
1227 }
1228
1229 /**
1230  * Transmit iSCSI PDU
1231  *
1232  * @v iscsi             iSCSI session
1233  * @v buf               Temporary data buffer
1234  * @v len               Length of temporary data buffer
1235  * 
1236  * Constructs data to be sent for the current TX state
1237  */
1238 static void iscsi_tx_step ( struct process *process ) {
1239         struct iscsi_session *iscsi =
1240                 container_of ( process, struct iscsi_session, process );
1241         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1242         int ( * tx ) ( struct iscsi_session *iscsi );
1243         enum iscsi_tx_state next_state;
1244         size_t tx_len;
1245         int rc;
1246
1247         /* Select fragment to transmit */
1248         while ( 1 ) {
1249                 switch ( iscsi->tx_state ) {
1250                 case ISCSI_TX_IDLE:
1251                         /* Stop processing */
1252                         return;
1253                 case ISCSI_TX_BHS:
1254                         tx = iscsi_tx_bhs;
1255                         tx_len = sizeof ( iscsi->tx_bhs );
1256                         next_state = ISCSI_TX_AHS;
1257                         break;
1258                 case ISCSI_TX_AHS:
1259                         tx = iscsi_tx_nothing;
1260                         tx_len = 0;
1261                         next_state = ISCSI_TX_DATA;
1262                         break;
1263                 case ISCSI_TX_DATA:
1264                         tx = iscsi_tx_data;
1265                         tx_len = ISCSI_DATA_LEN ( common->lengths );
1266                         next_state = ISCSI_TX_DATA_PADDING;
1267                         break;
1268                 case ISCSI_TX_DATA_PADDING:
1269                         tx = iscsi_tx_data_padding;
1270                         tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1271                         next_state = ISCSI_TX_IDLE;
1272                         break;
1273                 default:
1274                         assert ( 0 );
1275                         return;
1276                 }
1277
1278                 /* Check for window availability, if needed */
1279                 if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
1280                         /* Cannot transmit at this point; stop processing */
1281                         return;
1282                 }
1283
1284                 /* Transmit data */
1285                 if ( ( rc = tx ( iscsi ) ) != 0 ) {
1286                         DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
1287                                iscsi, strerror ( rc ) );
1288                         return;
1289                 }
1290
1291                 /* Move to next state */
1292                 iscsi->tx_state = next_state;
1293                 if ( next_state == ISCSI_TX_IDLE )
1294                         iscsi_tx_done ( iscsi );
1295         }
1296 }
1297
1298 /**
1299  * Receive basic header segment of an iSCSI PDU
1300  *
1301  * @v iscsi             iSCSI session
1302  * @v data              Received data
1303  * @v len               Length of received data
1304  * @v remaining         Data remaining after this data
1305  * @ret rc              Return status code
1306  *
1307  * This fills in iscsi::rx_bhs with the data from the BHS portion of
1308  * the received PDU.
1309  */
1310 static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
1311                           size_t len, size_t remaining __unused ) {
1312         memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
1313         if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
1314                 DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
1315                         iscsi, iscsi->rx_bhs.common.opcode,
1316                         ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
1317         }
1318         return 0;
1319 }
1320
1321 /**
1322  * Discard portion of an iSCSI PDU.
1323  *
1324  * @v iscsi             iSCSI session
1325  * @v data              Received data
1326  * @v len               Length of received data
1327  * @v remaining         Data remaining after this data
1328  * @ret rc              Return status code
1329  *
1330  * This discards data from a portion of a received PDU.
1331  */
1332 static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
1333                               const void *data __unused, size_t len __unused,
1334                               size_t remaining __unused ) {
1335         /* Do nothing */
1336         return 0;
1337 }
1338
1339 /**
1340  * Receive data segment of an iSCSI PDU
1341  *
1342  * @v iscsi             iSCSI session
1343  * @v data              Received data
1344  * @v len               Length of received data
1345  * @v remaining         Data remaining after this data
1346  * @ret rc              Return status code
1347  *
1348  * Handle processing of part of a PDU data segment.  iscsi::rx_bhs
1349  * will be valid when this is called.
1350  */
1351 static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
1352                            size_t len, size_t remaining ) {
1353         struct iscsi_bhs_common_response *response
1354                 = &iscsi->rx_bhs.common_response;
1355
1356         /* Update cmdsn and statsn */
1357         iscsi->cmdsn = ntohl ( response->expcmdsn );
1358         iscsi->statsn = ntohl ( response->statsn );
1359
1360         switch ( response->opcode & ISCSI_OPCODE_MASK ) {
1361         case ISCSI_OPCODE_LOGIN_RESPONSE:
1362                 return iscsi_rx_login_response ( iscsi, data, len, remaining );
1363         case ISCSI_OPCODE_SCSI_RESPONSE:
1364                 return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
1365         case ISCSI_OPCODE_DATA_IN:
1366                 return iscsi_rx_data_in ( iscsi, data, len, remaining );
1367         case ISCSI_OPCODE_R2T:
1368                 return iscsi_rx_r2t ( iscsi, data, len, remaining );
1369         default:
1370                 if ( remaining )
1371                         return 0;
1372                 DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
1373                        response->opcode );
1374                 return -ENOTSUP_OPCODE;
1375         }
1376 }
1377
1378 /**
1379  * Receive new data
1380  *
1381  * @v socket            Transport layer interface
1382  * @v data              Received data
1383  * @v len               Length of received data
1384  * @ret rc              Return status code
1385  *
1386  * This handles received PDUs.  The receive strategy is to fill in
1387  * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
1388  * throw away any AHS portion, and then process each part of the data
1389  * portion as it arrives.  The data processing routine therefore
1390  * always has a full copy of the BHS available, even for portions of
1391  * the data in different packets to the BHS.
1392  */
1393 static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
1394                                       const void *data, size_t len ) {
1395         struct iscsi_session *iscsi =
1396                 container_of ( socket, struct iscsi_session, socket );
1397         struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
1398         int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
1399                        size_t len, size_t remaining );
1400         enum iscsi_rx_state next_state;
1401         size_t frag_len;
1402         size_t remaining;
1403         int rc;
1404
1405         while ( 1 ) {
1406                 switch ( iscsi->rx_state ) {
1407                 case ISCSI_RX_BHS:
1408                         rx = iscsi_rx_bhs;
1409                         iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1410                         next_state = ISCSI_RX_AHS;                      
1411                         break;
1412                 case ISCSI_RX_AHS:
1413                         rx = iscsi_rx_discard;
1414                         iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1415                         next_state = ISCSI_RX_DATA;
1416                         break;
1417                 case ISCSI_RX_DATA:
1418                         rx = iscsi_rx_data;
1419                         iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1420                         next_state = ISCSI_RX_DATA_PADDING;
1421                         break;
1422                 case ISCSI_RX_DATA_PADDING:
1423                         rx = iscsi_rx_discard;
1424                         iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1425                         next_state = ISCSI_RX_BHS;
1426                         break;
1427                 default:
1428                         assert ( 0 );
1429                         return -EINVAL;
1430                 }
1431
1432                 frag_len = iscsi->rx_len - iscsi->rx_offset;
1433                 if ( frag_len > len )
1434                         frag_len = len;
1435                 remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
1436                 if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
1437                         DBGC ( iscsi, "iSCSI %p could not process received "
1438                                "data: %s\n", iscsi, strerror ( rc ) );
1439                         iscsi_close_connection ( iscsi, rc );
1440                         iscsi_scsi_done ( iscsi, rc );
1441                         return rc;
1442                 }
1443
1444                 iscsi->rx_offset += frag_len;
1445                 data += frag_len;
1446                 len -= frag_len;
1447
1448                 /* If all the data for this state has not yet been
1449                  * received, stay in this state for now.
1450                  */
1451                 if ( iscsi->rx_offset != iscsi->rx_len )
1452                         return 0;
1453
1454                 iscsi->rx_state = next_state;
1455                 iscsi->rx_offset = 0;
1456         }
1457
1458         return 0;
1459 }
1460
1461 /**
1462  * Handle stream connection closure
1463  *
1464  * @v socket            Transport layer interface
1465  * @v rc                Reason for close
1466  *
1467  */
1468 static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
1469         struct iscsi_session *iscsi =
1470                 container_of ( socket, struct iscsi_session, socket );
1471
1472         /* Even a graceful close counts as an error for iSCSI */
1473         if ( ! rc )
1474                 rc = -ECONNRESET;
1475
1476         /* Close session cleanly */
1477         iscsi_close_connection ( iscsi, rc );
1478
1479         /* Retry connection if within the retry limit, otherwise fail */
1480         if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1481                 DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
1482                        iscsi, iscsi->retry_count );
1483                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1484                         DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
1485                                iscsi, strerror ( rc ) );
1486                         iscsi_scsi_done ( iscsi, rc );
1487                 }
1488         } else {
1489                 DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
1490                 iscsi->instant_rc = rc;
1491                 iscsi_scsi_done ( iscsi, rc );
1492         }
1493 }
1494
1495 /**
1496  * Handle redirection event
1497  *
1498  * @v socket            Transport layer interface
1499  * @v type              Location type
1500  * @v args              Remaining arguments depend upon location type
1501  * @ret rc              Return status code
1502  */
1503 static int iscsi_vredirect ( struct xfer_interface *socket, int type,
1504                              va_list args ) {
1505         struct iscsi_session *iscsi =
1506                 container_of ( socket, struct iscsi_session, socket );
1507         va_list tmp;
1508         struct sockaddr *peer;
1509
1510         /* Intercept redirects to a LOCATION_SOCKET and record the IP
1511          * address for the iBFT.  This is a bit of a hack, but avoids
1512          * inventing an ioctl()-style call to retrieve the socket
1513          * address from a data-xfer interface.
1514          */
1515         if ( type == LOCATION_SOCKET ) {
1516                 va_copy ( tmp, args );
1517                 ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
1518                 peer = va_arg ( tmp, struct sockaddr * );
1519                 memcpy ( &iscsi->target_sockaddr, peer,
1520                          sizeof ( iscsi->target_sockaddr ) );
1521                 va_end ( tmp );
1522         }
1523
1524         return xfer_vreopen ( socket, type, args );
1525 }
1526                              
1527
1528 /** iSCSI socket operations */
1529 static struct xfer_interface_operations iscsi_socket_operations = {
1530         .close          = iscsi_socket_close,
1531         .vredirect      = iscsi_vredirect,
1532         .window         = unlimited_xfer_window,
1533         .alloc_iob      = default_xfer_alloc_iob,
1534         .deliver_iob    = xfer_deliver_as_raw,
1535         .deliver_raw    = iscsi_socket_deliver_raw,
1536 };
1537
1538
1539 /****************************************************************************
1540  *
1541  * iSCSI command issuing
1542  *
1543  */
1544
1545 /**
1546  * Issue SCSI command
1547  *
1548  * @v scsi              SCSI device
1549  * @v command           SCSI command
1550  * @ret rc              Return status code
1551  */
1552 static int iscsi_command ( struct scsi_device *scsi,
1553                            struct scsi_command *command ) {
1554         struct iscsi_session *iscsi =
1555                 container_of ( scsi->backend, struct iscsi_session, refcnt );
1556         int rc;
1557
1558         /* Abort immediately if we have a recorded permanent failure */
1559         if ( iscsi->instant_rc )
1560                 return iscsi->instant_rc;
1561
1562         /* Record SCSI command */
1563         iscsi->command = command;
1564
1565         /* Issue command or open connection as appropriate */
1566         if ( iscsi->status ) {
1567                 iscsi_start_command ( iscsi );
1568         } else {
1569                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1570                         iscsi->command = NULL;
1571                         return rc;
1572                 }
1573         }
1574
1575         return 0;
1576 }
1577
1578 /**
1579  * Shut down iSCSI interface
1580  *
1581  * @v scsi              SCSI device
1582  */
1583 void iscsi_detach ( struct scsi_device *scsi ) {
1584         struct iscsi_session *iscsi =
1585                 container_of ( scsi->backend, struct iscsi_session, refcnt );
1586
1587         xfer_nullify ( &iscsi->socket );
1588         iscsi_close_connection ( iscsi, 0 );
1589         process_del ( &iscsi->process );
1590         scsi->command = scsi_detached_command;
1591         ref_put ( scsi->backend );
1592         scsi->backend = NULL;
1593 }
1594
1595 /****************************************************************************
1596  *
1597  * Instantiator
1598  *
1599  */
1600
1601 /** iSCSI root path components (as per RFC4173) */
1602 enum iscsi_root_path_component {
1603         RP_LITERAL = 0,
1604         RP_SERVERNAME,
1605         RP_PROTOCOL,
1606         RP_PORT,
1607         RP_LUN,
1608         RP_TARGETNAME,
1609         NUM_RP_COMPONENTS
1610 };
1611
1612 /**
1613  * Parse iSCSI root path
1614  *
1615  * @v iscsi             iSCSI session
1616  * @v root_path         iSCSI root path (as per RFC4173)
1617  * @ret rc              Return status code
1618  */
1619 static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
1620                                    const char *root_path ) {
1621         char rp_copy[ strlen ( root_path ) + 1 ];
1622         char *rp_comp[NUM_RP_COMPONENTS];
1623         char *rp = rp_copy;
1624         int i = 0;
1625         int rc;
1626
1627         /* Split root path into component parts */
1628         strcpy ( rp_copy, root_path );
1629         while ( 1 ) {
1630                 rp_comp[i++] = rp;
1631                 if ( i == NUM_RP_COMPONENTS )
1632                         break;
1633                 for ( ; *rp != ':' ; rp++ ) {
1634                         if ( ! *rp ) {
1635                                 DBGC ( iscsi, "iSCSI %p root path \"%s\" "
1636                                        "too short\n", iscsi, root_path );
1637                                 return -EINVAL;
1638                         }
1639                 }
1640                 *(rp++) = '\0';
1641         }
1642
1643         /* Use root path components to configure iSCSI session */
1644         iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
1645         if ( ! iscsi->target_address )
1646                 return -ENOMEM;
1647         iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
1648         if ( ! iscsi->target_port )
1649                 iscsi->target_port = ISCSI_PORT;
1650         if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
1651                 DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
1652                        iscsi, rp_comp[RP_LUN] );
1653                 return rc;
1654         }
1655         iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
1656         if ( ! iscsi->target_iqn )
1657                 return -ENOMEM;
1658
1659         return 0;
1660 }
1661
1662 /**
1663  * Set iSCSI authentication details
1664  *
1665  * @v iscsi             iSCSI session
1666  * @v initiator_username Initiator username, if any
1667  * @v initiator_password Initiator password, if any
1668  * @v target_username   Target username, if any
1669  * @v target_password   Target password, if any
1670  * @ret rc              Return status code
1671  */
1672 static int iscsi_set_auth ( struct iscsi_session *iscsi,
1673                             const char *initiator_username,
1674                             const char *initiator_password,
1675                             const char *target_username,
1676                             const char *target_password ) {
1677
1678         /* Check for initiator or target credentials */
1679         if ( initiator_username || initiator_password ||
1680              target_username || target_password ) {
1681
1682                 /* We must have at least an initiator username+password */
1683                 if ( ! ( initiator_username && initiator_password ) )
1684                         goto invalid_auth;
1685
1686                 /* Store initiator credentials */
1687                 iscsi->initiator_username = strdup ( initiator_username );
1688                 if ( ! iscsi->initiator_username )
1689                         return -ENOMEM;
1690                 iscsi->initiator_password = strdup ( initiator_password );
1691                 if ( ! iscsi->initiator_password )
1692                         return -ENOMEM;
1693
1694                 /* Check for target credentials */
1695                 if ( target_username || target_password ) {
1696
1697                         /* We must have target username+password */
1698                         if ( ! ( target_username && target_password ) )
1699                                 goto invalid_auth;
1700
1701                         /* Store target credentials */
1702                         iscsi->target_username = strdup ( target_username );
1703                         if ( ! iscsi->target_username )
1704                                 return -ENOMEM;
1705                         iscsi->target_password = strdup ( target_password );
1706                         if ( ! iscsi->target_password )
1707                                 return -ENOMEM;
1708                 }
1709         }
1710
1711         return 0;
1712
1713  invalid_auth:
1714         DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
1715                "%sname,%spw, target %sname,%spw\n", iscsi,
1716                ( initiator_username ? "" : "no " ),
1717                ( initiator_password ? "" : "no " ),
1718                ( target_username ? "" : "no " ),
1719                ( target_password ? "" : "no " ) );
1720         return -EINVAL;
1721 }
1722
1723 /**
1724  * Attach iSCSI interface
1725  *
1726  * @v scsi              SCSI device
1727  * @v root_path         iSCSI root path (as per RFC4173)
1728  * @ret rc              Return status code
1729  */
1730 int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
1731         struct iscsi_session *iscsi;
1732         int rc;
1733
1734         /* Allocate and initialise structure */
1735         iscsi = zalloc ( sizeof ( *iscsi ) );
1736         if ( ! iscsi )
1737                 return -ENOMEM;
1738         iscsi->refcnt.free = iscsi_free;
1739         xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt );
1740         process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
1741
1742         /* Parse root path */
1743         if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
1744                 goto err;
1745         /* Set fields not specified by root path */
1746         if ( ( rc = iscsi_set_auth ( iscsi,
1747                                      iscsi_initiator_username,
1748                                      iscsi_initiator_password,
1749                                      iscsi_target_username,
1750                                      iscsi_target_password ) ) != 0 )
1751                 goto err;
1752
1753         /* Sanity checks */
1754         if ( ! iscsi->target_address ) {
1755                 DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
1756                        iscsi );
1757                 rc = -ENOTSUP_DISCOVERY;
1758                 goto err;
1759         }
1760         if ( ! iscsi->target_iqn ) {
1761                 DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
1762                        iscsi, root_path );
1763                 rc = -EINVAL;
1764                 goto err;
1765         }
1766
1767         /* Attach parent interface, mortalise self, and return */
1768         scsi->backend = ref_get ( &iscsi->refcnt );
1769         scsi->command = iscsi_command;
1770         ref_put ( &iscsi->refcnt );
1771         return 0;
1772         
1773  err:
1774         ref_put ( &iscsi->refcnt );
1775         return rc;
1776 }
1777
1778 /****************************************************************************
1779  *
1780  * Settings
1781  *
1782  */
1783
1784 /** iSCSI initiator IQN setting */
1785 struct setting initiator_iqn_setting __setting = {
1786         .name = "initiator-iqn",
1787         .description = "iSCSI initiator name",
1788         .tag = DHCP_ISCSI_INITIATOR_IQN,
1789         .type = &setting_type_string,
1790 };
1791
1792 /** iSCSI reverse username setting */
1793 struct setting reverse_username_setting __setting = {
1794         .name = "reverse-username",
1795         .description = "Reverse user name",
1796         .tag = DHCP_EB_REVERSE_USERNAME,
1797         .type = &setting_type_string,
1798 };
1799
1800 /** iSCSI reverse password setting */
1801 struct setting reverse_password_setting __setting = {
1802         .name = "reverse-password",
1803         .description = "Reverse password",
1804         .tag = DHCP_EB_REVERSE_PASSWORD,
1805         .type = &setting_type_string,
1806 };
1807
1808 /** An iSCSI string setting */
1809 struct iscsi_string_setting {
1810         /** Setting */
1811         struct setting *setting;
1812         /** String to update */
1813         char **string;
1814         /** String prefix */
1815         const char *prefix;
1816 };
1817
1818 /** iSCSI string settings */
1819 static struct iscsi_string_setting iscsi_string_settings[] = {
1820         {
1821                 .setting = &initiator_iqn_setting,
1822                 .string = &iscsi_explicit_initiator_iqn,
1823                 .prefix = "",
1824         },
1825         {
1826                 .setting = &username_setting,
1827                 .string = &iscsi_initiator_username,
1828                 .prefix = "",
1829         },
1830         {
1831                 .setting = &password_setting,
1832                 .string = &iscsi_initiator_password,
1833                 .prefix = "",
1834         },
1835         {
1836                 .setting = &reverse_username_setting,
1837                 .string = &iscsi_target_username,
1838                 .prefix = "",
1839         },
1840         {
1841                 .setting = &reverse_password_setting,
1842                 .string = &iscsi_target_password,
1843                 .prefix = "",
1844         },
1845         {
1846                 .setting = &hostname_setting,
1847                 .string = &iscsi_default_initiator_iqn,
1848                 .prefix = "iqn.2000-01.org.etherboot:",
1849         },
1850 };
1851
1852 /**
1853  * Apply iSCSI setting
1854  *
1855  * @v setting           iSCSI string setting
1856  * @ret rc              Return status code
1857  */
1858 static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
1859         size_t prefix_len;
1860         int setting_len;
1861         size_t len;
1862         int check_len;
1863         char *p;
1864
1865         /* Free old string */
1866         free ( *setting->string );
1867         *setting->string = NULL;
1868
1869         /* Allocate new string */
1870         prefix_len = strlen ( setting->prefix );
1871         setting_len = fetch_setting_len ( NULL, setting->setting );
1872         if ( setting_len < 0 ) {
1873                 /* Missing settings are not errors; leave strings as NULL */
1874                 return 0;
1875         }
1876         len = ( prefix_len + setting_len + 1 );
1877         p = *setting->string = malloc ( len );
1878         if ( ! p )
1879                 return -ENOMEM;
1880
1881         /* Fill new string */
1882         strcpy ( p, setting->prefix );
1883         check_len = fetch_string_setting ( NULL, setting->setting,
1884                                            ( p + prefix_len ),
1885                                            ( len - prefix_len ) );
1886         assert ( check_len == setting_len );
1887
1888         return 0;
1889 }
1890
1891 /**
1892  * Apply iSCSI settings
1893  *
1894  * @ret rc              Return status code
1895  */
1896 static int apply_iscsi_settings ( void ) {
1897         struct iscsi_string_setting *setting;
1898         unsigned int i;
1899         int rc;
1900
1901         for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
1902                             sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
1903                 setting = &iscsi_string_settings[i];
1904                 if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
1905                         DBG ( "iSCSI could not apply setting %s\n",
1906                               setting->setting->name );
1907                         return rc;
1908                 }
1909         }
1910
1911         return 0;
1912 }
1913
1914 /** iSCSI settings applicator */
1915 struct settings_applicator iscsi_settings_applicator __settings_applicator = {
1916         .apply = apply_iscsi_settings,
1917 };
1918
1919 /****************************************************************************
1920  *
1921  * Initiator name
1922  *
1923  */
1924
1925 /**
1926  * Get iSCSI initiator IQN
1927  *
1928  * @v iscsi             iSCSI session
1929  * @ret rc              Return status code
1930  */
1931 const char * iscsi_initiator_iqn ( void ) {
1932
1933         if ( iscsi_explicit_initiator_iqn )
1934                 return iscsi_explicit_initiator_iqn;
1935         if ( iscsi_default_initiator_iqn )
1936                 return iscsi_default_initiator_iqn;
1937         return "iqn.2000-09.org.etherboot:UNKNOWN";
1938 }