|
@@ -41,16 +41,16 @@
|
41
|
41
|
*/
|
42
|
42
|
|
43
|
43
|
/** iSCSI initiator name (explicitly specified) */
|
44
|
|
-char *iscsi_initiator_iqn;
|
|
44
|
+static char *iscsi_explicit_initiator_iqn;
|
45
|
45
|
|
46
|
46
|
/** Default iSCSI initiator name (constructed from hostname) */
|
47
|
|
-char *iscsi_default_initiator_iqn;
|
|
47
|
+static char *iscsi_default_initiator_iqn;
|
48
|
48
|
|
49
|
49
|
/** iSCSI username */
|
50
|
|
-char *iscsi_username;
|
|
50
|
+static char *iscsi_username;
|
51
|
51
|
|
52
|
52
|
/** iSCSI password */
|
53
|
|
-char *iscsi_password;
|
|
53
|
+static char *iscsi_password;
|
54
|
54
|
|
55
|
55
|
static void iscsi_start_tx ( struct iscsi_session *iscsi );
|
56
|
56
|
static void iscsi_start_login ( struct iscsi_session *iscsi );
|
|
@@ -78,6 +78,8 @@ static void iscsi_free ( struct refcnt *refcnt ) {
|
78
|
78
|
|
79
|
79
|
free ( iscsi->target_address );
|
80
|
80
|
free ( iscsi->target_iqn );
|
|
81
|
+ free ( iscsi->username );
|
|
82
|
+ free ( iscsi->password );
|
81
|
83
|
chap_finish ( &iscsi->chap );
|
82
|
84
|
iscsi_rx_buffered_data_done ( iscsi );
|
83
|
85
|
free ( iscsi );
|
|
@@ -436,22 +438,16 @@ static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
|
436
|
438
|
*/
|
437
|
439
|
static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
|
438
|
440
|
void *data, size_t len ) {
|
439
|
|
- char *initiator_iqn;
|
440
|
441
|
unsigned int used = 0;
|
441
|
442
|
unsigned int i;
|
442
|
443
|
|
443
|
444
|
if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
|
444
|
|
- initiator_iqn = iscsi_initiator_iqn;
|
445
|
|
- if ( ! initiator_iqn )
|
446
|
|
- initiator_iqn = iscsi_default_initiator_iqn;
|
447
|
|
- if ( ! initiator_iqn )
|
448
|
|
- initiator_iqn = "iqn.2000-09.org.etherboot:UNKNOWN";
|
449
|
445
|
used += ssnprintf ( data + used, len - used,
|
450
|
446
|
"InitiatorName=%s%c"
|
451
|
447
|
"TargetName=%s%c"
|
452
|
448
|
"SessionType=Normal%c"
|
453
|
449
|
"AuthMethod=CHAP,None%c",
|
454
|
|
- initiator_iqn, 0,
|
|
450
|
+ iscsi_initiator_iqn(), 0,
|
455
|
451
|
iscsi->target_iqn, 0, 0, 0 );
|
456
|
452
|
}
|
457
|
453
|
|
|
@@ -460,10 +456,10 @@ static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
|
460
|
456
|
}
|
461
|
457
|
|
462
|
458
|
if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) &&
|
463
|
|
- iscsi_username ) {
|
|
459
|
+ iscsi->username ) {
|
464
|
460
|
used += ssnprintf ( data + used, len - used,
|
465
|
461
|
"CHAP_N=%s%cCHAP_R=0x",
|
466
|
|
- iscsi_username, 0 );
|
|
462
|
+ iscsi->username, 0 );
|
467
|
463
|
for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
|
468
|
464
|
used += ssnprintf ( data + used, len - used, "%02x",
|
469
|
465
|
iscsi->chap.response[i] );
|
|
@@ -647,9 +643,9 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
|
647
|
643
|
* challenge.
|
648
|
644
|
*/
|
649
|
645
|
chap_set_identifier ( &iscsi->chap, identifier );
|
650
|
|
- if ( iscsi_password ) {
|
651
|
|
- chap_update ( &iscsi->chap, iscsi_password,
|
652
|
|
- strlen ( iscsi_password ) );
|
|
646
|
+ if ( iscsi->password ) {
|
|
647
|
+ chap_update ( &iscsi->chap, iscsi->password,
|
|
648
|
+ strlen ( iscsi->password ) );
|
653
|
649
|
}
|
654
|
650
|
|
655
|
651
|
return 0;
|
|
@@ -1279,10 +1275,43 @@ static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
|
1279
|
1275
|
}
|
1280
|
1276
|
}
|
1281
|
1277
|
|
|
1278
|
+/**
|
|
1279
|
+ * Handle redirection event
|
|
1280
|
+ *
|
|
1281
|
+ * @v socket Transport layer interface
|
|
1282
|
+ * @v type Location type
|
|
1283
|
+ * @v args Remaining arguments depend upon location type
|
|
1284
|
+ * @ret rc Return status code
|
|
1285
|
+ */
|
|
1286
|
+static int iscsi_vredirect ( struct xfer_interface *socket, int type,
|
|
1287
|
+ va_list args ) {
|
|
1288
|
+ struct iscsi_session *iscsi =
|
|
1289
|
+ container_of ( socket, struct iscsi_session, socket );
|
|
1290
|
+ va_list tmp;
|
|
1291
|
+ struct sockaddr *peer;
|
|
1292
|
+
|
|
1293
|
+ /* Intercept redirects to a LOCATION_SOCKET and record the IP
|
|
1294
|
+ * address for the iBFT. This is a bit of a hack, but avoids
|
|
1295
|
+ * inventing an ioctl()-style call to retrieve the socket
|
|
1296
|
+ * address from a data-xfer interface.
|
|
1297
|
+ */
|
|
1298
|
+ if ( type == LOCATION_SOCKET ) {
|
|
1299
|
+ va_copy ( tmp, args );
|
|
1300
|
+ ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
|
|
1301
|
+ peer = va_arg ( tmp, struct sockaddr * );
|
|
1302
|
+ memcpy ( &iscsi->target_sockaddr, peer,
|
|
1303
|
+ sizeof ( iscsi->target_sockaddr ) );
|
|
1304
|
+ va_end ( tmp );
|
|
1305
|
+ }
|
|
1306
|
+
|
|
1307
|
+ return xfer_vopen ( socket, type, args );
|
|
1308
|
+}
|
|
1309
|
+
|
|
1310
|
+
|
1282
|
1311
|
/** iSCSI socket operations */
|
1283
|
1312
|
static struct xfer_interface_operations iscsi_socket_operations = {
|
1284
|
1313
|
.close = iscsi_socket_close,
|
1285
|
|
- .vredirect = xfer_vopen,
|
|
1314
|
+ .vredirect = iscsi_vredirect,
|
1286
|
1315
|
.seek = ignore_xfer_seek,
|
1287
|
1316
|
.window = unlimited_xfer_window,
|
1288
|
1317
|
.alloc_iob = default_xfer_alloc_iob,
|
|
@@ -1460,6 +1489,32 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
|
1460
|
1489
|
return 0;
|
1461
|
1490
|
}
|
1462
|
1491
|
|
|
1492
|
+/**
|
|
1493
|
+ * Set iSCSI authentication details
|
|
1494
|
+ *
|
|
1495
|
+ * @v iscsi iSCSI session
|
|
1496
|
+ * @v username Username, if any
|
|
1497
|
+ * @v password Password, if any
|
|
1498
|
+ * @ret rc Return status code
|
|
1499
|
+ */
|
|
1500
|
+static int iscsi_set_auth ( struct iscsi_session *iscsi,
|
|
1501
|
+ const char *username, const char *password ) {
|
|
1502
|
+
|
|
1503
|
+ if ( username ) {
|
|
1504
|
+ iscsi->username = strdup ( username );
|
|
1505
|
+ if ( ! iscsi->username )
|
|
1506
|
+ return -ENOMEM;
|
|
1507
|
+ }
|
|
1508
|
+
|
|
1509
|
+ if ( password ) {
|
|
1510
|
+ iscsi->password = strdup ( password );
|
|
1511
|
+ if ( ! iscsi->password )
|
|
1512
|
+ return -ENOMEM;
|
|
1513
|
+ }
|
|
1514
|
+
|
|
1515
|
+ return 0;
|
|
1516
|
+}
|
|
1517
|
+
|
1463
|
1518
|
/**
|
1464
|
1519
|
* Attach iSCSI interface
|
1465
|
1520
|
*
|
|
@@ -1482,6 +1537,10 @@ int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
|
1482
|
1537
|
/* Parse root path */
|
1483
|
1538
|
if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
|
1484
|
1539
|
goto err;
|
|
1540
|
+ /* Set fields not specified by root path */
|
|
1541
|
+ if ( ( rc = iscsi_set_auth ( iscsi, iscsi_username,
|
|
1542
|
+ iscsi_password ) ) != 0 )
|
|
1543
|
+ goto err;
|
1485
|
1544
|
|
1486
|
1545
|
/* Sanity checks */
|
1487
|
1546
|
if ( ! iscsi->target_address ) {
|
|
@@ -1533,7 +1592,7 @@ static int apply_dhcp_iscsi_string ( unsigned int tag,
|
1533
|
1592
|
/* Identify string and prefix */
|
1534
|
1593
|
switch ( tag ) {
|
1535
|
1594
|
case DHCP_ISCSI_INITIATOR_IQN:
|
1536
|
|
- string = &iscsi_initiator_iqn;
|
|
1595
|
+ string = &iscsi_explicit_initiator_iqn;
|
1537
|
1596
|
break;
|
1538
|
1597
|
case DHCP_EB_USERNAME:
|
1539
|
1598
|
string = &iscsi_username;
|
|
@@ -1584,3 +1643,24 @@ struct dhcp_option_applicator dhcp_iscsi_applicators[] __dhcp_applicator = {
|
1584
|
1643
|
.apply = apply_dhcp_iscsi_string,
|
1585
|
1644
|
},
|
1586
|
1645
|
};
|
|
1646
|
+
|
|
1647
|
+/****************************************************************************
|
|
1648
|
+ *
|
|
1649
|
+ * Initiator name
|
|
1650
|
+ *
|
|
1651
|
+ */
|
|
1652
|
+
|
|
1653
|
+/**
|
|
1654
|
+ * Get iSCSI initiator IQN
|
|
1655
|
+ *
|
|
1656
|
+ * @v iscsi iSCSI session
|
|
1657
|
+ * @ret rc Return status code
|
|
1658
|
+ */
|
|
1659
|
+const char * iscsi_initiator_iqn ( void ) {
|
|
1660
|
+
|
|
1661
|
+ if ( iscsi_explicit_initiator_iqn )
|
|
1662
|
+ return iscsi_explicit_initiator_iqn;
|
|
1663
|
+ if ( iscsi_default_initiator_iqn )
|
|
1664
|
+ return iscsi_default_initiator_iqn;
|
|
1665
|
+ return "iqn.2000-09.org.etherboot:UNKNOWN";
|
|
1666
|
+}
|