500f18906b626218c56a8055062e9f8ac18fbbb2
[people/sha0/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 #include <stddef.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <byteswap.h>
26 #include <gpxe/vsprintf.h>
27 #include <gpxe/socket.h>
28 #include <gpxe/xfer.h>
29 #include <gpxe/open.h>
30 #include <gpxe/scsi.h>
31 #include <gpxe/process.h>
32 #include <gpxe/uaccess.h>
33 #include <gpxe/tcpip.h>
34 #include <gpxe/iscsi.h>
35
36 /** @file
37  *
38  * iSCSI protocol
39  *
40  */
41
42 static void iscsi_start_tx ( struct iscsi_session *iscsi );
43 static void iscsi_start_login ( struct iscsi_session *iscsi );
44 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
45                                    unsigned int datasn );
46
47 /**
48  * Finish receiving PDU data into buffer
49  *
50  * @v iscsi             iSCSI session
51  */
52 static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
53         free ( iscsi->rx_buffer );
54         iscsi->rx_buffer = NULL;
55 }
56
57 /**
58  * Free iSCSI session
59  *
60  * @v refcnt            Reference counter
61  */
62 static void iscsi_free ( struct refcnt *refcnt ) {
63         struct iscsi_session *iscsi =
64                 container_of ( refcnt, struct iscsi_session, refcnt );
65
66         free ( iscsi->initiator_iqn );
67         free ( iscsi->target_address );
68         free ( iscsi->target_iqn );
69         free ( iscsi->username );
70         free ( iscsi->password );
71         chap_finish ( &iscsi->chap );
72         iscsi_rx_buffered_data_done ( iscsi );
73         free ( iscsi );
74 }
75
76 /**
77  * Open iSCSI transport-layer connection
78  *
79  * @v iscsi             iSCSI session
80  * @ret rc              Return status code
81  */
82 static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
83         struct sockaddr_tcpip target;
84         int rc;
85
86         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
87         assert ( iscsi->rx_state == ISCSI_RX_BHS );
88         assert ( iscsi->rx_offset == 0 );
89
90         /* Open socket */
91         memset ( &target, 0, sizeof ( target ) );
92         target.st_port = htons ( ISCSI_PORT );
93         if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
94                                              ( struct sockaddr * ) &target,
95                                              iscsi->target_address,
96                                              NULL ) ) != 0 ) {
97                 DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
98                        iscsi, strerror ( rc ) );
99                 return rc;
100         }
101
102         /* Enter security negotiation phase */
103         iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
104                           ISCSI_STATUS_STRINGS_SECURITY );
105
106         /* Assign fresh initiator task tag */
107         iscsi->itt++;
108
109         /* Initiate login */
110         iscsi_start_login ( iscsi );
111
112         return 0;
113 }
114
115 /**
116  * Close iSCSI transport-layer connection
117  *
118  * @v iscsi             iSCSI session
119  * @v rc                Reason for close
120  *
121  * Closes the transport-layer connection and resets the session state
122  * ready to attempt a fresh login.
123  */
124 static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
125
126         /* Close all data transfer interfaces */
127         xfer_close ( &iscsi->socket, rc );
128
129         /* Clear connection status */
130         iscsi->status = 0;
131
132         /* Reset TX and RX state machines */
133         iscsi->tx_state = ISCSI_TX_IDLE;
134         iscsi->rx_state = ISCSI_RX_BHS;
135
136         /* Free any temporary dynamically allocated memory */
137         chap_finish ( &iscsi->chap );
138         iscsi_rx_buffered_data_done ( iscsi );
139 }
140
141 /**
142  * Mark iSCSI SCSI operation as complete
143  *
144  * @v iscsi             iSCSI session
145  * @v rc                Return status code
146  *
147  * Note that iscsi_scsi_done() will not close the connection, and must
148  * therefore be called only when the internal state machines are in an
149  * appropriate state, otherwise bad things may happen on the next call
150  * to iscsi_issue().  The general rule is to call iscsi_scsi_done()
151  * only at the end of receiving a PDU; at this point the TX and RX
152  * engines should both be idle.
153  */
154 static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
155
156         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
157
158         /* Clear current SCSI command */
159         iscsi->command = NULL;
160
161         /* Mark asynchronous operation as complete */
162         async_done ( &iscsi->async, rc );
163 }
164
165 /****************************************************************************
166  *
167  * iSCSI SCSI command issuing
168  *
169  */
170
171 /**
172  * Build iSCSI SCSI command BHS
173  *
174  * @v iscsi             iSCSI session
175  *
176  * We don't currently support bidirectional commands (i.e. with both
177  * Data-In and Data-Out segments); these would require providing code
178  * to generate an AHS, and there doesn't seem to be any need for it at
179  * the moment.
180  */
181 static void iscsi_start_command ( struct iscsi_session *iscsi ) {
182         struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
183
184         assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
185
186         /* Construct BHS and initiate transmission */
187         iscsi_start_tx ( iscsi );
188         command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
189         command->flags = ( ISCSI_FLAG_FINAL |
190                            ISCSI_COMMAND_ATTR_SIMPLE );
191         if ( iscsi->command->data_in )
192                 command->flags |= ISCSI_COMMAND_FLAG_READ;
193         if ( iscsi->command->data_out )
194                 command->flags |= ISCSI_COMMAND_FLAG_WRITE;
195         /* lengths left as zero */
196         command->lun = iscsi->lun;
197         command->itt = htonl ( ++iscsi->itt );
198         command->exp_len = htonl ( iscsi->command->data_in_len |
199                                    iscsi->command->data_out_len );
200         command->cmdsn = htonl ( iscsi->cmdsn );
201         command->expstatsn = htonl ( iscsi->statsn + 1 );
202         memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
203         DBGC ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#x\n",
204                iscsi, SCSI_CDB_DATA ( command->cdb ),
205                ( iscsi->command->data_in ? "in" : "out" ),
206                ( iscsi->command->data_in ?
207                  iscsi->command->data_in_len : iscsi->command->data_out_len ));
208 }
209
210 /**
211  * Receive data segment of an iSCSI SCSI response PDU
212  *
213  * @v iscsi             iSCSI session
214  * @v data              Received data
215  * @v len               Length of received data
216  * @v remaining         Data remaining after this data
217  * @ret rc              Return status code
218  */
219 static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
220                                     const void *data, size_t len,
221                                     size_t remaining ) {
222         struct iscsi_bhs_scsi_response *response
223                 = &iscsi->rx_bhs.scsi_response;
224         int sense_offset;
225
226         /* Capture the sense response code as it floats past, if present */
227         sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
228         if ( ( sense_offset >= 0 ) && len ) {
229                 iscsi->command->sense_response =
230                         * ( ( char * ) data + sense_offset );
231         }
232
233         /* Wait for whole SCSI response to arrive */
234         if ( remaining )
235                 return 0;
236         
237         /* Record SCSI status code */
238         iscsi->command->status = response->status;
239
240         /* Check for errors */
241         if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
242                 return -EIO;
243
244         /* Mark as completed */
245         iscsi_scsi_done ( iscsi, 0 );
246         return 0;
247 }
248
249 /**
250  * Receive data segment of an iSCSI data-in PDU
251  *
252  * @v iscsi             iSCSI session
253  * @v data              Received data
254  * @v len               Length of received data
255  * @v remaining         Data remaining after this data
256  * @ret rc              Return status code
257  */
258 static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
259                               const void *data, size_t len,
260                               size_t remaining __unused ) {
261         struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
262         unsigned long offset;
263
264         /* Copy data to data-in buffer */
265         offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
266         assert ( iscsi->command != NULL );
267         assert ( iscsi->command->data_in );
268         assert ( ( offset + len ) <= iscsi->command->data_in_len );
269         copy_to_user ( iscsi->command->data_in, offset, data, len );
270
271         /* Record SCSI status, if present */
272         if ( data_in->flags & ISCSI_DATA_FLAG_STATUS )
273                 iscsi->command->status = data_in->status;
274
275         /* If this is the end, flag as complete */
276         if ( ( offset + len ) == iscsi->command->data_in_len ) {
277                 assert ( data_in->flags & ISCSI_FLAG_FINAL );
278                 assert ( remaining == 0 );
279                 iscsi_scsi_done ( iscsi, 0 );
280         }
281
282         return 0;
283 }
284
285 /**
286  * Receive data segment of an iSCSI R2T PDU
287  *
288  * @v iscsi             iSCSI session
289  * @v data              Received data
290  * @v len               Length of received data
291  * @v remaining         Data remaining after this data
292  * @ret rc              Return status code
293  */
294 static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
295                           const void *data __unused, size_t len __unused,
296                           size_t remaining __unused ) {
297         struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
298
299         /* Record transfer parameters and trigger first data-out */
300         iscsi->ttt = ntohl ( r2t->ttt );
301         iscsi->transfer_offset = ntohl ( r2t->offset );
302         iscsi->transfer_len = ntohl ( r2t->len );
303         iscsi_start_data_out ( iscsi, 0 );
304
305         return 0;
306 }
307
308 /**
309  * Build iSCSI data-out BHS
310  *
311  * @v iscsi             iSCSI session
312  * @v datasn            Data sequence number within the transfer
313  *
314  */
315 static void iscsi_start_data_out ( struct iscsi_session *iscsi,
316                                    unsigned int datasn ) {
317         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
318         unsigned long offset;
319         unsigned long remaining;
320         unsigned long len;
321
322         /* We always send 512-byte Data-Out PDUs; this removes the
323          * need to worry about the target's MaxRecvDataSegmentLength.
324          */
325         offset = datasn * 512;
326         remaining = iscsi->transfer_len - offset;
327         len = remaining;
328         if ( len > 512 )
329                 len = 512;
330
331         /* Construct BHS and initiate transmission */
332         iscsi_start_tx ( iscsi );
333         data_out->opcode = ISCSI_OPCODE_DATA_OUT;
334         if ( len == remaining )
335                 data_out->flags = ( ISCSI_FLAG_FINAL );
336         ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
337         data_out->lun = iscsi->lun;
338         data_out->itt = htonl ( iscsi->itt );
339         data_out->ttt = htonl ( iscsi->ttt );
340         data_out->expstatsn = htonl ( iscsi->statsn + 1 );
341         data_out->datasn = htonl ( datasn );
342         data_out->offset = htonl ( iscsi->transfer_offset + offset );
343         DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
344                iscsi, datasn, len );
345 }
346
347 /**
348  * Complete iSCSI data-out PDU transmission
349  *
350  * @v iscsi             iSCSI session
351  *
352  */
353 static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
354         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
355
356         /* If we haven't reached the end of the sequence, start
357          * sending the next data-out PDU.
358          */
359         if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
360                 iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
361 }
362
363 /**
364  * Send iSCSI data-out data segment
365  *
366  * @v iscsi             iSCSI session
367  * @ret rc              Return status code
368  */
369 static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
370         struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
371         struct io_buffer *iobuf;
372         unsigned long offset;
373         size_t len;
374
375         offset = ntohl ( data_out->offset );
376         len = ISCSI_DATA_LEN ( data_out->lengths );
377
378         assert ( iscsi->command != NULL );
379         assert ( iscsi->command->data_out );
380         assert ( ( offset + len ) <= iscsi->command->data_out_len );
381
382         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
383         if ( ! iobuf )
384                 return -ENOMEM;
385         
386         copy_from_user ( iob_put ( iobuf, len ),
387                          iscsi->command->data_out, offset, len );
388
389         return xfer_deliver_iob ( &iscsi->socket, iobuf );
390 }
391
392 /****************************************************************************
393  *
394  * iSCSI login
395  *
396  */
397
398 /**
399  * Build iSCSI login request strings
400  *
401  * @v iscsi             iSCSI session
402  *
403  * These are the initial set of strings sent in the first login
404  * request PDU.  We want the following settings:
405  *
406  *     HeaderDigest=None
407  *     DataDigest=None
408  *     MaxConnections is irrelevant; we make only one connection anyway
409  *     InitialR2T=Yes [1]
410  *     ImmediateData is irrelevant; we never send immediate data
411  *     MaxRecvDataSegmentLength=8192 (default; we don't care)
412  *     MaxBurstLength=262144 (default; we don't care)
413  *     FirstBurstLength=262144 (default; we don't care)
414  *     DefaultTime2Wait=0 [2]
415  *     DefaultTime2Retain=0 [2]
416  *     MaxOutstandingR2T=1
417  *     DataPDUInOrder=Yes
418  *     DataSequenceInOrder=Yes
419  *     ErrorRecoveryLevel=0
420  *
421  * [1] InitialR2T has an OR resolution function, so the target may
422  * force us to use it.  We therefore simplify our logic by always
423  * using it.
424  *
425  * [2] These ensure that we can safely start a new task once we have
426  * reconnected after a failure, without having to manually tidy up
427  * after the old one.
428  */
429 static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
430                                                void *data, size_t len ) {
431         unsigned int used = 0;
432         unsigned int i;
433
434         if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
435                 used += ssnprintf ( data + used, len - used,
436                                     "InitiatorName=%s%c"
437                                     "TargetName=%s%c"
438                                     "SessionType=Normal%c"
439                                     "AuthMethod=CHAP,None%c",
440                                     iscsi->initiator_iqn, 0,
441                                     iscsi->target_iqn, 0, 0, 0 );
442         }
443
444         if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
445                 used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
446         }
447         
448         if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) &&
449              iscsi->username ) {
450                 used += ssnprintf ( data + used, len - used,
451                                     "CHAP_N=%s%cCHAP_R=0x",
452                                     iscsi->username, 0 );
453                 for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
454                         used += ssnprintf ( data + used, len - used, "%02x",
455                                             iscsi->chap.response[i] );
456                 }
457                 used += ssnprintf ( data + used, len - used, "%c", 0 );
458         }
459
460         if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
461                 used += ssnprintf ( data + used, len - used,
462                                     "HeaderDigest=None%c"
463                                     "DataDigest=None%c"
464                                     "InitialR2T=Yes%c"
465                                     "DefaultTime2Wait=0%c"
466                                     "DefaultTime2Retain=0%c"
467                                     "MaxOutstandingR2T=1%c"
468                                     "DataPDUInOrder=Yes%c"
469                                     "DataSequenceInOrder=Yes%c"
470                                     "ErrorRecoveryLevel=0%c",
471                                     0, 0, 0, 0, 0, 0, 0, 0, 0 );
472         }
473
474         return used;
475 }
476
477 /**
478  * Build iSCSI login request BHS
479  *
480  * @v iscsi             iSCSI session
481  */
482 static void iscsi_start_login ( struct iscsi_session *iscsi ) {
483         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
484         int len;
485
486         /* Construct BHS and initiate transmission */
487         iscsi_start_tx ( iscsi );
488         request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
489                             ISCSI_FLAG_IMMEDIATE );
490         request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
491                            ISCSI_LOGIN_FLAG_TRANSITION );
492         /* version_max and version_min left as zero */
493         len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
494         ISCSI_SET_LENGTHS ( request->lengths, 0, len );
495         request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
496                                         IANA_EN_FEN_SYSTEMS );
497         /* isid_iana_qual left as zero */
498         request->tsih = htons ( iscsi->tsih );
499         request->itt = htonl ( iscsi->itt );
500         /* cid left as zero */
501         request->cmdsn = htonl ( iscsi->cmdsn );
502         request->expstatsn = htonl ( iscsi->statsn + 1 );
503 }
504
505 /**
506  * Complete iSCSI login request PDU transmission
507  *
508  * @v iscsi             iSCSI session
509  *
510  */
511 static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
512
513         /* Clear any "strings to send" flags */
514         iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
515
516         /* Free any dynamically allocated storage used for login */
517         chap_finish ( &iscsi->chap );
518 }
519
520 /**
521  * Transmit data segment of an iSCSI login request PDU
522  *
523  * @v iscsi             iSCSI session
524  * @ret rc              Return status code
525  *
526  * For login requests, the data segment consists of the login strings.
527  */
528 static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
529         struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
530         struct io_buffer *iobuf;
531         size_t len;
532
533         len = ISCSI_DATA_LEN ( request->lengths );
534         iobuf = xfer_alloc_iob ( &iscsi->socket, len );
535         if ( ! iobuf )
536                 return -ENOMEM;
537         iob_put ( iobuf, len );
538         iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
539         return xfer_deliver_iob ( &iscsi->socket, iobuf );
540 }
541
542 /**
543  * Handle iSCSI TargetAddress text value
544  *
545  * @v iscsi             iSCSI session
546  * @v value             TargetAddress value
547  * @ret rc              Return status code
548  */
549 static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
550                                               const char *value ) {
551
552         DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
553
554         /* Replace target address */
555         free ( iscsi->target_address );
556         iscsi->target_address = strdup ( value );
557         if ( ! iscsi->target_address )
558                 return -ENOMEM;
559         return 0;
560 }
561
562 /**
563  * Handle iSCSI AuthMethod text value
564  *
565  * @v iscsi             iSCSI session
566  * @v value             AuthMethod value
567  * @ret rc              Return status code
568  */
569 static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
570                                            const char *value ) {
571
572         /* If server requests CHAP, send the CHAP_A string */
573         if ( strcmp ( value, "CHAP" ) == 0 ) {
574                 DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
575                        iscsi );
576                 iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_ALGORITHM;
577         }
578         return 0;
579 }
580
581 /**
582  * Handle iSCSI CHAP_A text value
583  *
584  * @v iscsi             iSCSI session
585  * @v value             CHAP_A value
586  * @ret rc              Return status code
587  */
588 static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
589                                        const char *value ) {
590         int rc;
591
592         /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
593          * the server responds with anything else it is a protocol
594          * violation.
595          */
596         if ( strcmp ( value, "5" ) != 0 ) {
597                 DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
598                        iscsi, value );
599                 return -EPROTO;
600         }
601
602         /* Prepare for CHAP with MD5 */
603         if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
604                 DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
605                        iscsi, strerror ( rc ) );
606                 return rc;
607         }
608
609         return 0;
610 }
611
612 /**
613  * Handle iSCSI CHAP_I text value
614  *
615  * @v iscsi             iSCSI session
616  * @v value             CHAP_I value
617  * @ret rc              Return status code
618  */
619 static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
620                                        const char *value ) {
621         unsigned int identifier;
622         char *endp;
623
624         /* The CHAP identifier is an integer value */
625         identifier = strtoul ( value, &endp, 0 );
626         if ( *endp != '\0' ) {
627                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
628                        iscsi, value );
629                 return -EPROTO;
630         }
631
632         /* Identifier and secret are the first two components of the
633          * challenge.
634          */
635         chap_set_identifier ( &iscsi->chap, identifier );
636         if ( iscsi->password ) {
637                 chap_update ( &iscsi->chap, iscsi->password,
638                               strlen ( iscsi->password ) );
639         }
640
641         return 0;
642 }
643
644 /**
645  * Handle iSCSI CHAP_C text value
646  *
647  * @v iscsi             iSCSI session
648  * @v value             CHAP_C value
649  * @ret rc              Return status code
650  */
651 static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
652                                        const char *value ) {
653         char buf[3];
654         char *endp;
655         uint8_t byte;
656
657         /* Check and strip leading "0x" */
658         if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
659                 DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
660                        iscsi, value );
661         }
662         value += 2;
663
664         /* Process challenge an octet at a time */
665         for ( ; ( value[0] && value[1] ) ; value += 2 ) {
666                 memcpy ( buf, value, 2 );
667                 buf[3] = 0;
668                 byte = strtoul ( buf, &endp, 16 );
669                 if ( *endp != '\0' ) {
670                         DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
671                                "byte \"%s\"\n", iscsi, buf );
672                         return -EPROTO;
673                 }
674                 chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
675         }
676
677         /* Build CHAP response */
678         DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
679         chap_respond ( &iscsi->chap );
680         iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
681
682         return 0;
683 }
684
685 /** An iSCSI text string that we want to handle */
686 struct iscsi_string_type {
687         /** String key
688          *
689          * This is the portion up to and including the "=" sign,
690          * e.g. "InitiatorName=", "CHAP_A=", etc.
691          */
692         const char *key;
693         /** Handle iSCSI string value
694          *
695          * @v iscsi             iSCSI session
696          * @v value             iSCSI string value
697          * @ret rc              Return status code
698          */
699         int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
700 };
701
702 /** iSCSI text strings that we want to handle */
703 struct iscsi_string_type iscsi_string_types[] = {
704         { "TargetAddress=", iscsi_handle_targetaddress_value },
705         { "AuthMethod=", iscsi_handle_authmethod_value },
706         { "CHAP_A=", iscsi_handle_chap_a_value },
707         { "CHAP_I=", iscsi_handle_chap_i_value },
708         { "CHAP_C=", iscsi_handle_chap_c_value },
709         { NULL, NULL }
710 };
711
712 /**
713  * Handle iSCSI string
714  *
715  * @v iscsi             iSCSI session
716  * @v string            iSCSI string (in "key=value" format)
717  * @ret rc              Return status code
718  */
719 static int iscsi_handle_string ( struct iscsi_session *iscsi,
720                                  const char *string ) {
721         struct iscsi_string_type *type;
722         size_t key_len;
723         int rc;
724
725         for ( type = iscsi_string_types ; type->key ; type++ ) {
726                 key_len = strlen ( type->key );
727                 if ( strncmp ( string, type->key, key_len ) != 0 )
728                         continue;
729                 DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
730                 if ( ( rc = type->handle ( iscsi,
731                                            ( string + key_len ) ) ) != 0 ) {
732                         DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
733                                iscsi, string, strerror ( rc ) );
734                         return rc;
735                 }
736                 return 0;
737         }
738         DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
739         return 0;
740 }
741
742 /**
743  * Handle iSCSI strings
744  *
745  * @v iscsi             iSCSI session
746  * @v string            iSCSI string buffer
747  * @v len               Length of string buffer
748  * @ret rc              Return status code
749  */
750 static int iscsi_handle_strings ( struct iscsi_session *iscsi,
751                                   const char *strings, size_t len ) {
752         size_t string_len;
753         int rc;
754
755         /* Handle each string in turn, taking care not to overrun the
756          * data buffer in case of badly-terminated data.
757          */
758         while ( 1 ) {
759                 string_len = ( strnlen ( strings, len ) + 1 );
760                 if ( string_len > len )
761                         break;
762                 if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
763                         return rc;
764                 strings += string_len;
765                 len -= string_len;
766         }
767         return 0;
768 }
769
770 /**
771  * Receive PDU data into buffer
772  *
773  * @v iscsi             iSCSI session
774  * @v data              Data to receive
775  * @v len               Length of data
776  * @ret rc              Return status code
777  *
778  * This can be used when the RX PDU type handler wishes to buffer up
779  * all received data and process the PDU as a single unit.  The caller
780  * is repsonsible for calling iscsi_rx_buffered_data_done() after
781  * processing the data.
782  */
783 static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
784                                     const void *data, size_t len ) {
785
786         /* Allocate buffer on first call */
787         if ( ! iscsi->rx_buffer ) {
788                 iscsi->rx_buffer = malloc ( iscsi->rx_len );
789                 if ( ! iscsi->rx_buffer )
790                         return -ENOMEM;
791         }
792
793         /* Copy data to buffer */
794         assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
795         memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
796
797         return 0;
798 }
799
800 /**
801  * Receive data segment of an iSCSI login response PDU
802  *
803  * @v iscsi             iSCSI session
804  * @v data              Received data
805  * @v len               Length of received data
806  * @v remaining         Data remaining after this data
807  * @ret rc              Return status code
808  */
809 static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
810                                      const void *data, size_t len,
811                                      size_t remaining ) {
812         struct iscsi_bhs_login_response *response
813                 = &iscsi->rx_bhs.login_response;
814         int rc;
815
816         /* Buffer up the PDU data */
817         if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
818                 DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
819                        iscsi, strerror ( rc ) );
820                 return rc;
821         }
822         if ( remaining )
823                 return 0;
824
825         /* Process string data and discard string buffer */
826         if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
827                                            iscsi->rx_len ) ) != 0 )
828                 return rc;
829         iscsi_rx_buffered_data_done ( iscsi );
830
831         /* Check for login redirection */
832         if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
833                 DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
834                 iscsi_close_connection ( iscsi, 0 );
835                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
836                         DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
837                                iscsi, strerror ( rc ) );
838                         return rc;
839                 }
840                 return 0;
841         }
842
843         /* Check for fatal errors */
844         if ( response->status_class != 0 ) {
845                 DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
846                        response->status_class, response->status_detail );
847                 iscsi->instant_rc = -EPERM;
848                 return -EPERM;
849         }
850
851         /* Handle login transitions */
852         if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
853                 switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
854                 case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
855                         iscsi->status =
856                                 ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
857                                   ISCSI_STATUS_STRINGS_OPERATIONAL );
858                         break;
859                 case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
860                         iscsi->status = ISCSI_STATUS_FULL_FEATURE_PHASE;
861                         break;
862                 default:
863                         DBGC ( iscsi, "iSCSI %p got invalid response flags "
864                                "%02x\n", iscsi, response->flags );
865                         return -EIO;
866                 }
867         }
868
869         /* Send next login request PDU if we haven't reached the full
870          * feature phase yet.
871          */
872         if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
873              ISCSI_STATUS_FULL_FEATURE_PHASE ) {
874                 iscsi_start_login ( iscsi );
875                 return 0;
876         }
877
878         /* Reset retry count */
879         iscsi->retry_count = 0;
880
881         /* Record TSIH for future reference */
882         iscsi->tsih = ntohl ( response->tsih );
883         
884         /* Send the actual SCSI command */
885         iscsi_start_command ( iscsi );
886
887         return 0;
888 }
889
890 /****************************************************************************
891  *
892  * iSCSI to socket interface
893  *
894  */
895
896 /**
897  * Start up a new TX PDU
898  *
899  * @v iscsi             iSCSI session
900  *
901  * This initiates the process of sending a new PDU.  Only one PDU may
902  * be in transit at any one time.
903  */
904 static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
905         assert ( iscsi->tx_state == ISCSI_TX_IDLE );
906         
907         /* Initialise TX BHS */
908         memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
909
910         /* Flag TX engine to start transmitting */
911         iscsi->tx_state = ISCSI_TX_BHS;
912 }
913
914 /**
915  * Transmit basic header segment of an iSCSI PDU
916  *
917  * @v iscsi             iSCSI session
918  * @ret rc              Return status code
919  */
920 static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
921         return xfer_deliver_raw ( &iscsi->socket,  &iscsi->tx_bhs,
922                                   sizeof ( iscsi->tx_bhs ) );
923 }
924
925 /**
926  * Transmit data segment of an iSCSI PDU
927  *
928  * @v iscsi             iSCSI session
929  * @ret rc              Return status code
930  * 
931  * Handle transmission of part of a PDU data segment.  iscsi::tx_bhs
932  * will be valid when this is called.
933  */
934 static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
935         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
936
937         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
938         case ISCSI_OPCODE_DATA_OUT:
939                 return iscsi_tx_data_out ( iscsi );
940         case ISCSI_OPCODE_LOGIN_REQUEST:
941                 return iscsi_tx_login_request ( iscsi );
942         default:
943                 assert ( 0 );
944                 return -EINVAL;
945         }
946 }
947
948 /**
949  * Transmit data padding of an iSCSI PDU
950  *
951  * @v iscsi             iSCSI session
952  * @ret rc              Return status code
953  * 
954  * Handle transmission of any data padding in a PDU data segment.
955  * iscsi::tx_bhs will be valid when this is called.
956  */
957 static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
958         static const char pad[] = { '\0', '\0', '\0' };
959         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
960         size_t pad_len;
961         
962         pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
963         if ( ! pad_len )
964                 return 0;
965
966         return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
967 }
968
969 /**
970  * Complete iSCSI PDU transmission
971  *
972  * @v iscsi             iSCSI session
973  *
974  * Called when a PDU has been completely transmitted and the TX state
975  * machine is about to enter the idle state.  iscsi::tx_bhs will be
976  * valid for the just-completed PDU when this is called.
977  */
978 static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
979         struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
980
981         switch ( common->opcode & ISCSI_OPCODE_MASK ) {
982         case ISCSI_OPCODE_DATA_OUT:
983                 iscsi_data_out_done ( iscsi );
984         case ISCSI_OPCODE_LOGIN_REQUEST:
985                 iscsi_login_request_done ( iscsi );
986         default:
987                 /* No action */
988                 break;
989         }
990 }
991
992 /**
993  * Transmit iSCSI PDU
994  *
995  * @v iscsi             iSCSI session
996  * @v buf               Temporary data buffer
997  * @v len               Length of temporary data buffer
998  * 
999  * Constructs data to be sent for the current TX state
1000  */
1001 static void iscsi_tx_step ( struct process *process ) {
1002         struct iscsi_session *iscsi =
1003                 container_of ( process, struct iscsi_session, process );
1004         int rc = 0;
1005
1006         if ( xfer_window ( &iscsi->socket ) == 0 )
1007                 return;
1008
1009         switch ( iscsi->tx_state ) {
1010         case ISCSI_TX_IDLE:
1011                 /* Nothing to send */
1012                 break;
1013         case ISCSI_TX_BHS:
1014                 if ( ( rc = iscsi_tx_bhs ( iscsi ) ) != 0 )
1015                         break;
1016                 iscsi->tx_state = ISCSI_TX_AHS;
1017                 break;
1018         case ISCSI_TX_AHS:
1019                 /* We don't yet have an AHS transmission mechanism */
1020                 iscsi->tx_state = ISCSI_TX_DATA;
1021                 break;
1022         case ISCSI_TX_DATA:
1023                 if ( ( rc = iscsi_tx_data ( iscsi ) ) != 0 )
1024                         break;
1025                 iscsi->tx_state = ISCSI_TX_DATA_PADDING;
1026                 break;
1027         case ISCSI_TX_DATA_PADDING:
1028                 if ( ( rc = iscsi_tx_data_padding ( iscsi ) ) != 0 )
1029                         break;
1030                 iscsi->tx_state = ISCSI_TX_IDLE;
1031                 iscsi_tx_done ( iscsi );
1032                 break;
1033         default:
1034                 assert ( 0 );
1035                 break;
1036         }
1037 }
1038
1039 /**
1040  * Receive basic header segment of an iSCSI PDU
1041  *
1042  * @v iscsi             iSCSI session
1043  * @v data              Received data
1044  * @v len               Length of received data
1045  * @v remaining         Data remaining after this data
1046  * @ret rc              Return status code
1047  *
1048  * This fills in iscsi::rx_bhs with the data from the BHS portion of
1049  * the received PDU.
1050  */
1051 static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
1052                           size_t len, size_t remaining __unused ) {
1053         memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
1054         if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
1055                 DBGC ( iscsi, "iSCSI %p received PDU opcode %#x len %#lx\n",
1056                        iscsi, iscsi->rx_bhs.common.opcode,
1057                        ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
1058         }
1059         return 0;
1060 }
1061
1062 /**
1063  * Discard portion of an iSCSI PDU.
1064  *
1065  * @v iscsi             iSCSI session
1066  * @v data              Received data
1067  * @v len               Length of received data
1068  * @v remaining         Data remaining after this data
1069  * @ret rc              Return status code
1070  *
1071  * This discards data from a portion of a received PDU.
1072  */
1073 static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
1074                               const void *data __unused, size_t len __unused,
1075                               size_t remaining __unused ) {
1076         /* Do nothing */
1077         return 0;
1078 }
1079
1080 /**
1081  * Receive data segment of an iSCSI PDU
1082  *
1083  * @v iscsi             iSCSI session
1084  * @v data              Received data
1085  * @v len               Length of received data
1086  * @v remaining         Data remaining after this data
1087  * @ret rc              Return status code
1088  *
1089  * Handle processing of part of a PDU data segment.  iscsi::rx_bhs
1090  * will be valid when this is called.
1091  */
1092 static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
1093                            size_t len, size_t remaining ) {
1094         struct iscsi_bhs_common_response *response
1095                 = &iscsi->rx_bhs.common_response;
1096
1097         /* Update cmdsn and statsn */
1098         iscsi->cmdsn = ntohl ( response->expcmdsn );
1099         iscsi->statsn = ntohl ( response->statsn );
1100
1101         switch ( response->opcode & ISCSI_OPCODE_MASK ) {
1102         case ISCSI_OPCODE_LOGIN_RESPONSE:
1103                 return iscsi_rx_login_response ( iscsi, data, len, remaining );
1104         case ISCSI_OPCODE_SCSI_RESPONSE:
1105                 return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
1106         case ISCSI_OPCODE_DATA_IN:
1107                 return iscsi_rx_data_in ( iscsi, data, len, remaining );
1108         case ISCSI_OPCODE_R2T:
1109                 return iscsi_rx_r2t ( iscsi, data, len, remaining );
1110         default:
1111                 if ( remaining )
1112                         return 0;
1113                 DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
1114                        response->opcode );
1115                 return -EOPNOTSUPP;
1116         }
1117 }
1118
1119 /**
1120  * Receive new data
1121  *
1122  * @v socket            Transport layer interface
1123  * @v data              Received data
1124  * @v len               Length of received data
1125  * @ret rc              Return status code
1126  *
1127  * This handles received PDUs.  The receive strategy is to fill in
1128  * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
1129  * throw away any AHS portion, and then process each part of the data
1130  * portion as it arrives.  The data processing routine therefore
1131  * always has a full copy of the BHS available, even for portions of
1132  * the data in different packets to the BHS.
1133  */
1134 static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
1135                                       const void *data, size_t len ) {
1136         struct iscsi_session *iscsi =
1137                 container_of ( socket, struct iscsi_session, socket );
1138         struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
1139         int ( *process ) ( struct iscsi_session *iscsi, const void *data,
1140                            size_t len, size_t remaining );
1141         enum iscsi_rx_state next_state;
1142         size_t frag_len;
1143         size_t remaining;
1144         int rc;
1145
1146         while ( 1 ) {
1147                 switch ( iscsi->rx_state ) {
1148                 case ISCSI_RX_BHS:
1149                         process = iscsi_rx_bhs;
1150                         iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1151                         next_state = ISCSI_RX_AHS;                      
1152                         break;
1153                 case ISCSI_RX_AHS:
1154                         process = iscsi_rx_discard;
1155                         iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1156                         next_state = ISCSI_RX_DATA;
1157                         break;
1158                 case ISCSI_RX_DATA:
1159                         process = iscsi_rx_data;
1160                         iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1161                         next_state = ISCSI_RX_DATA_PADDING;
1162                         break;
1163                 case ISCSI_RX_DATA_PADDING:
1164                         process = iscsi_rx_discard;
1165                         iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1166                         next_state = ISCSI_RX_BHS;
1167                         break;
1168                 default:
1169                         assert ( 0 );
1170                         return -EINVAL;
1171                 }
1172
1173                 frag_len = iscsi->rx_len - iscsi->rx_offset;
1174                 if ( frag_len > len )
1175                         frag_len = len;
1176                 remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
1177                 if ( ( rc = process ( iscsi, data, frag_len,
1178                                       remaining ) ) != 0 ) {
1179                         DBGC ( iscsi, "iSCSI %p could not process received "
1180                                "data: %s\n", iscsi, strerror ( rc ) );
1181                         iscsi_close_connection ( iscsi, rc );
1182                         iscsi_scsi_done ( iscsi, rc );
1183                         return rc;
1184                 }
1185
1186                 iscsi->rx_offset += frag_len;
1187                 data += frag_len;
1188                 len -= frag_len;
1189
1190                 /* If all the data for this state has not yet been
1191                  * received, stay in this state for now.
1192                  */
1193                 if ( iscsi->rx_offset != iscsi->rx_len )
1194                         return 0;
1195
1196                 iscsi->rx_state = next_state;
1197                 iscsi->rx_offset = 0;
1198         }
1199
1200         return 0;
1201 }
1202
1203 /**
1204  * Handle stream connection closure
1205  *
1206  * @v socket            Transport layer interface
1207  * @v rc                Reason for close
1208  *
1209  */
1210 static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
1211         struct iscsi_session *iscsi =
1212                 container_of ( socket, struct iscsi_session, socket );
1213
1214         /* Even a graceful close counts as an error for iSCSI */
1215         if ( ! rc )
1216                 rc = -ECONNRESET;
1217
1218         /* Close session cleanly */
1219         iscsi_close_connection ( iscsi, rc );
1220
1221         /* Retry connection if within the retry limit, otherwise fail */
1222         if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1223                 DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
1224                        iscsi, iscsi->retry_count );
1225                 if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1226                         DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
1227                                iscsi, strerror ( rc ) );
1228                         iscsi_scsi_done ( iscsi, rc );
1229                 }
1230         } else {
1231                 DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
1232                 iscsi->instant_rc = rc;
1233                 iscsi_scsi_done ( iscsi, rc );
1234         }
1235 }
1236
1237 /** iSCSI socket operations */
1238 static struct xfer_interface_operations iscsi_socket_operations = {
1239         .close          = iscsi_socket_close,
1240         .vredirect      = xfer_vopen,
1241         .seek           = ignore_xfer_seek,
1242         .window         = unlimited_xfer_window,
1243         .alloc_iob      = default_xfer_alloc_iob,
1244         .deliver_iob    = xfer_deliver_as_raw,
1245         .deliver_raw    = iscsi_socket_deliver_raw,
1246 };
1247
1248 /**
1249  * Issue SCSI command via iSCSI session
1250  *
1251  * @v iscsi             iSCSI session
1252  * @v command           SCSI command
1253  * @v parent            Parent asynchronous operation
1254  * @ret rc              Return status code
1255  */
1256 int iscsi_issue ( struct iscsi_session *iscsi, struct scsi_command *command,
1257                   struct async *parent ) {
1258         int rc;
1259
1260         assert ( iscsi->command == NULL );
1261         iscsi->command = command;
1262
1263         if ( iscsi->instant_rc ) {
1264                 /* Abort immediately rather than retrying */
1265                 return iscsi->instant_rc;
1266         } else if ( iscsi->status ) {
1267                 /* Session already open: issue command */
1268                 iscsi_start_command ( iscsi );
1269                 stream_kick ( &iscsi->stream );
1270         } else {
1271                 /* Session not open: initiate login */
1272                 iscsi->stream.op = &iscsi_stream_operations;
1273                 if ( ( rc = tcp_open ( &iscsi->stream ) ) != 0 ) {
1274                         DBGC ( iscsi, "iSCSI %p could not open stream: %s\n ",
1275                                iscsi, strerror ( rc ) );
1276                         return rc;
1277                 }
1278                 if ( ( rc = stream_connect ( &iscsi->stream,
1279                                              &iscsi->target ) ) != 0 ) {
1280                         DBGC ( iscsi, "iSCSI %p could not connect: %s\n",
1281                                iscsi, strerror ( rc ) );
1282                         return rc;
1283                 }
1284         }
1285
1286         async_init ( &iscsi->async, &default_async_operations, parent );
1287         return 0;
1288 }
1289
1290 /**
1291  * Close down iSCSI session
1292  *
1293  * @v iscsi             iSCSI session
1294  * @ret aop             Asynchronous operation
1295  */
1296 void iscsi_shutdown ( struct iscsi_session *iscsi ) {
1297         iscsi_close_connection ( iscsi, 0 );
1298         ref_put ( &iscsi->refcnt );
1299 }