Handle TargetAddress
authorMichael Brown <mcb30@etherboot.org>
Tue, 5 Dec 2006 01:41:32 +0000 (01:41 +0000)
committerMichael Brown <mcb30@etherboot.org>
Tue, 5 Dec 2006 01:41:32 +0000 (01:41 +0000)
src/include/gpxe/iscsi.h
src/net/tcp/iscsi.c

index 8a264a2..2961a96 100644 (file)
@@ -221,6 +221,12 @@ struct iscsi_bhs_login_response {
 /** Login response opcode */
 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
 
+/* Login response status codes */
+#define ISCSI_STATUS_SUCCESS           0x00
+#define ISCSI_STATUS_REDIRECT          0x01
+#define ISCSI_STATUS_INITIATOR_ERROR   0x02
+#define ISCSI_STATUS_TARGET_ERROR      0x03
+
 /**
  * iSCSI SCSI command basic header segment
  *
index ae198c4..31d5a1b 100644 (file)
@@ -505,6 +505,27 @@ static void iscsi_tx_login_request ( struct iscsi_session *iscsi,
                   len - iscsi->tx_offset );
 }
 
+/**
+ * Handle iSCSI TargetAddress text value
+ *
+ * @v iscsi            iSCSI session
+ * @v value            TargetAddress value
+ */
+static void iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
+                                              const char *value ) {
+       struct in_addr address;
+       struct sockaddr_in *sin = ( struct sockaddr_in * ) &iscsi->tcp.peer;
+
+       if ( inet_aton ( value, &address ) == 0 ) {
+               DBG ( "iSCSI %p received invalid TargetAddress \"%s\"\n",
+                     iscsi, value );
+               return;
+       }
+
+       DBG ( "iSCSI %p will redirect to %s\n", iscsi, value );
+       sin->sin_addr = address;
+}
+
 /**
  * Handle iSCSI AuthMethod text value
  *
@@ -629,6 +650,7 @@ struct iscsi_string_type {
 
 /** iSCSI text strings that we want to handle */
 struct iscsi_string_type iscsi_string_types[] = {
+       { "TargetAddress=", iscsi_handle_targetaddress_value },
        { "AuthMethod=", iscsi_handle_authmethod_value },
        { "CHAP_A=", iscsi_handle_chap_a_value },
        { "CHAP_I=", iscsi_handle_chap_i_value },
@@ -710,6 +732,14 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
        iscsi_handle_strings ( iscsi, iscsi->rx_buffer, iscsi->rx_len );
        iscsi_rx_buffered_data_done ( iscsi );
 
+       /* Check for login redirection */
+       if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
+               DBG ( "iSCSI %p redirecting to new server\n", iscsi );
+               iscsi_close ( iscsi, -EINPROGRESS );
+               tcp_connect ( &iscsi->tcp );
+               return;
+       }
+
        /* Check for fatal errors */
        if ( response->status_class != 0 ) {
                printf ( "iSCSI login failure: class %02x detail %02x\n",