Browse Source

Prepare for iBFT merge when possible. iscsiboot.c contains a really,

really ugly hack at present, but that doesn't hugely matter since I'm
aiming to change the interface to iSCSI devices anyway within the next
week.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
47a86bca2d
4 changed files with 132 additions and 18 deletions
  1. 1
    0
      src/include/gpxe/errfile.h
  2. 9
    0
      src/include/gpxe/iscsi.h
  3. 98
    18
      src/net/tcp/iscsi.c
  4. 24
    0
      src/usr/iscsiboot.c

+ 1
- 0
src/include/gpxe/errfile.h View File

@@ -115,6 +115,7 @@
115 115
 #define ERRFILE_cipher		      ( ERRFILE_OTHER | 0x00090000 )
116 116
 #define ERRFILE_image_cmd	      ( ERRFILE_OTHER | 0x000a0000 )
117 117
 #define ERRFILE_uri_test	      ( ERRFILE_OTHER | 0x000b0000 )
118
+#define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
118 119
 
119 120
 /** @} */
120 121
 

+ 9
- 0
src/include/gpxe/iscsi.h View File

@@ -8,6 +8,7 @@
8 8
  */
9 9
 
10 10
 #include <stdint.h>
11
+#include <gpxe/socket.h>
11 12
 #include <gpxe/scsi.h>
12 13
 #include <gpxe/chap.h>
13 14
 #include <gpxe/refcnt.h>
@@ -501,6 +502,8 @@ struct iscsi_session {
501 502
 	char *target_iqn;
502 503
 	/** Logical Unit Number (LUN) */
503 504
 	uint64_t lun;
505
+	/** Target socket address (recorded only for iBFT) */
506
+	struct sockaddr target_sockaddr;
504 507
 
505 508
 	/** Session status
506 509
 	 *
@@ -514,6 +517,11 @@ struct iscsi_session {
514 517
 	 * Reset upon a successful connection.
515 518
 	 */
516 519
 	int retry_count;
520
+
521
+	/** Username (if any) */
522
+	char *username;
523
+	/** Password (if any) */
524
+	char *password;
517 525
 	/** CHAP challenge/response */
518 526
 	struct chap_challenge chap;
519 527
 
@@ -641,5 +649,6 @@ struct iscsi_session {
641 649
 
642 650
 extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path );
643 651
 extern void iscsi_detach ( struct scsi_device *scsi );
652
+extern const char * iscsi_initiator_iqn ( void );
644 653
 
645 654
 #endif /* _GPXE_ISCSI_H */

+ 98
- 18
src/net/tcp/iscsi.c View File

@@ -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
+}

+ 24
- 0
src/usr/iscsiboot.c View File

@@ -3,9 +3,27 @@
3 3
 #include <stdio.h>
4 4
 #include <gpxe/iscsi.h>
5 5
 #include <gpxe/dhcp.h>
6
+#include <gpxe/netdevice.h>
7
+#include <gpxe/ibft.h>
6 8
 #include <int13.h>
7 9
 #include <usr/iscsiboot.h>
8 10
 
11
+/**
12
+ * Guess boot network device
13
+ *
14
+ * @ret netdev		Boot network device
15
+ */
16
+static struct net_device * guess_boot_netdev ( void ) {
17
+	struct net_device *boot_netdev;
18
+
19
+	/* Just use the first network device */
20
+	for_each_netdev ( boot_netdev ) {
21
+		return boot_netdev;
22
+	}
23
+
24
+	return NULL;
25
+}
26
+
9 27
 int iscsiboot ( const char *root_path ) {
10 28
 	struct scsi_device scsi;
11 29
 	struct int13_drive drive;
@@ -30,6 +48,12 @@ int iscsiboot ( const char *root_path ) {
30 48
 	drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE );
31 49
 	drive.blockdev = &scsi.blockdev;
32 50
 
51
+	/* FIXME: ugly, ugly hack */
52
+	struct net_device *netdev = guess_boot_netdev();
53
+	struct iscsi_session *iscsi =
54
+		container_of ( scsi.backend, struct iscsi_session, refcnt );
55
+	ibft_fill_data ( netdev, iscsi );
56
+
33 57
 	register_int13_drive ( &drive );
34 58
 	printf ( "Registered as BIOS drive %#02x\n", drive.drive );
35 59
 	printf ( "Booting from BIOS drive %#02x\n", drive.drive );

Loading…
Cancel
Save