| 
				
			 | 
			
			
				
				@@ -31,6 +31,7 @@ 
			 | 
		
		
	
		
			
			| 
				31
			 | 
			
				31
			 | 
			
			
				
				 #include <gpxe/process.h> 
			 | 
		
		
	
		
			
			| 
				32
			 | 
			
				32
			 | 
			
			
				
				 #include <gpxe/uaccess.h> 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				33
			 | 
			
			
				
				 #include <gpxe/tcpip.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				34
			 | 
			
			
				
				+#include <gpxe/dhcp.h> 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				35
			 | 
			
			
				
				 #include <gpxe/iscsi.h> 
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				36
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				37
			 | 
			
			
				
				 /** @file 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -39,6 +40,18 @@ 
			 | 
		
		
	
		
			
			| 
				39
			 | 
			
				40
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				40
			 | 
			
				41
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				41
			 | 
			
				42
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				43
			 | 
			
			
				
				+/** iSCSI initiator name (explicitly specified) */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				44
			 | 
			
			
				
				+char *iscsi_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				45
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				46
			 | 
			
			
				
				+/** Default iSCSI initiator name (constructed from hostname) */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				47
			 | 
			
			
				
				+char *iscsi_default_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				48
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				49
			 | 
			
			
				
				+/** iSCSI username */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				50
			 | 
			
			
				
				+char *iscsi_username; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				51
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				52
			 | 
			
			
				
				+/** iSCSI password */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				53
			 | 
			
			
				
				+char *iscsi_password; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				54
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				42
			 | 
			
				55
			 | 
			
			
				
				 static void iscsi_start_tx ( struct iscsi_session *iscsi ); 
			 | 
		
		
	
		
			
			| 
				43
			 | 
			
				56
			 | 
			
			
				
				 static void iscsi_start_login ( struct iscsi_session *iscsi ); 
			 | 
		
		
	
		
			
			| 
				44
			 | 
			
				57
			 | 
			
			
				
				 static void iscsi_start_data_out ( struct iscsi_session *iscsi, 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -63,11 +76,8 @@ static void iscsi_free ( struct refcnt *refcnt ) { 
			 | 
		
		
	
		
			
			| 
				63
			 | 
			
				76
			 | 
			
			
				
				 	struct iscsi_session *iscsi = 
			 | 
		
		
	
		
			
			| 
				64
			 | 
			
				77
			 | 
			
			
				
				 		container_of ( refcnt, struct iscsi_session, refcnt ); 
			 | 
		
		
	
		
			
			| 
				65
			 | 
			
				78
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				66
			 | 
			
				
			 | 
			
			
				
				-	free ( iscsi->initiator_iqn ); 
			 | 
		
		
	
		
			
			| 
				67
			 | 
			
				79
			 | 
			
			
				
				 	free ( iscsi->target_address ); 
			 | 
		
		
	
		
			
			| 
				68
			 | 
			
				80
			 | 
			
			
				
				 	free ( iscsi->target_iqn ); 
			 | 
		
		
	
		
			
			| 
				69
			 | 
			
				
			 | 
			
			
				
				-	free ( iscsi->username ); 
			 | 
		
		
	
		
			
			| 
				70
			 | 
			
				
			 | 
			
			
				
				-	free ( iscsi->password ); 
			 | 
		
		
	
		
			
			| 
				71
			 | 
			
				81
			 | 
			
			
				
				 	chap_finish ( &iscsi->chap ); 
			 | 
		
		
	
		
			
			| 
				72
			 | 
			
				82
			 | 
			
			
				
				 	iscsi_rx_buffered_data_done ( iscsi ); 
			 | 
		
		
	
		
			
			| 
				73
			 | 
			
				83
			 | 
			
			
				
				 	free ( iscsi ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -89,7 +99,7 @@ static int iscsi_open_connection ( struct iscsi_session *iscsi ) { 
			 | 
		
		
	
		
			
			| 
				89
			 | 
			
				99
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				90
			 | 
			
				100
			 | 
			
			
				
				 	/* Open socket */ 
			 | 
		
		
	
		
			
			| 
				91
			 | 
			
				101
			 | 
			
			
				
				 	memset ( &target, 0, sizeof ( target ) ); 
			 | 
		
		
	
		
			
			| 
				92
			 | 
			
				
			 | 
			
			
				
				-	target.st_port = htons ( ISCSI_PORT ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				
				+	target.st_port = htons ( iscsi->target_port ); 
			 | 
		
		
	
		
			
			| 
				93
			 | 
			
				103
			 | 
			
			
				
				 	if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM, 
			 | 
		
		
	
		
			
			| 
				94
			 | 
			
				104
			 | 
			
			
				
				 					     ( struct sockaddr * ) &target, 
			 | 
		
		
	
		
			
			| 
				95
			 | 
			
				105
			 | 
			
			
				
				 					     iscsi->target_address, 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -428,16 +438,22 @@ static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) { 
			 | 
		
		
	
		
			
			| 
				428
			 | 
			
				438
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				429
			 | 
			
				439
			 | 
			
			
				
				 static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi, 
			 | 
		
		
	
		
			
			| 
				430
			 | 
			
				440
			 | 
			
			
				
				 					       void *data, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				441
			 | 
			
			
				
				+	char *initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				431
			 | 
			
				442
			 | 
			
			
				
				 	unsigned int used = 0; 
			 | 
		
		
	
		
			
			| 
				432
			 | 
			
				443
			 | 
			
			
				
				 	unsigned int i; 
			 | 
		
		
	
		
			
			| 
				433
			 | 
			
				444
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				434
			 | 
			
				445
			 | 
			
			
				
				 	if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				446
			 | 
			
			
				
				+		initiator_iqn = iscsi_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				447
			 | 
			
			
				
				+		if ( ! initiator_iqn ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				448
			 | 
			
			
				
				+			initiator_iqn = iscsi_default_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				449
			 | 
			
			
				
				+		if ( ! initiator_iqn ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				450
			 | 
			
			
				
				+			initiator_iqn = "iqn.2000-09.org.etherboot:UNKNOWN"; 
			 | 
		
		
	
		
			
			| 
				435
			 | 
			
				451
			 | 
			
			
				
				 		used += ssnprintf ( data + used, len - used, 
			 | 
		
		
	
		
			
			| 
				436
			 | 
			
				452
			 | 
			
			
				
				 				    "InitiatorName=%s%c" 
			 | 
		
		
	
		
			
			| 
				437
			 | 
			
				453
			 | 
			
			
				
				 				    "TargetName=%s%c" 
			 | 
		
		
	
		
			
			| 
				438
			 | 
			
				454
			 | 
			
			
				
				 				    "SessionType=Normal%c" 
			 | 
		
		
	
		
			
			| 
				439
			 | 
			
				455
			 | 
			
			
				
				 				    "AuthMethod=CHAP,None%c", 
			 | 
		
		
	
		
			
			| 
				440
			 | 
			
				
			 | 
			
			
				
				-				    iscsi->initiator_iqn, 0, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				456
			 | 
			
			
				
				+				    initiator_iqn, 0, 
			 | 
		
		
	
		
			
			| 
				441
			 | 
			
				457
			 | 
			
			
				
				 				    iscsi->target_iqn, 0, 0, 0 ); 
			 | 
		
		
	
		
			
			| 
				442
			 | 
			
				458
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				443
			 | 
			
				459
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -446,10 +462,10 @@ static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi, 
			 | 
		
		
	
		
			
			| 
				446
			 | 
			
				462
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				447
			 | 
			
				463
			 | 
			
			
				
				 	 
			 | 
		
		
	
		
			
			| 
				448
			 | 
			
				464
			 | 
			
			
				
				 	if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) && 
			 | 
		
		
	
		
			
			| 
				449
			 | 
			
				
			 | 
			
			
				
				-	     iscsi->username ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				465
			 | 
			
			
				
				+	     iscsi_username ) { 
			 | 
		
		
	
		
			
			| 
				450
			 | 
			
				466
			 | 
			
			
				
				 		used += ssnprintf ( data + used, len - used, 
			 | 
		
		
	
		
			
			| 
				451
			 | 
			
				467
			 | 
			
			
				
				 				    "CHAP_N=%s%cCHAP_R=0x", 
			 | 
		
		
	
		
			
			| 
				452
			 | 
			
				
			 | 
			
			
				
				-				    iscsi->username, 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				468
			 | 
			
			
				
				+				    iscsi_username, 0 ); 
			 | 
		
		
	
		
			
			| 
				453
			 | 
			
				469
			 | 
			
			
				
				 		for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				454
			 | 
			
				470
			 | 
			
			
				
				 			used += ssnprintf ( data + used, len - used, "%02x", 
			 | 
		
		
	
		
			
			| 
				455
			 | 
			
				471
			 | 
			
			
				
				 					    iscsi->chap.response[i] ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -633,9 +649,9 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi, 
			 | 
		
		
	
		
			
			| 
				633
			 | 
			
				649
			 | 
			
			
				
				 	 * challenge. 
			 | 
		
		
	
		
			
			| 
				634
			 | 
			
				650
			 | 
			
			
				
				 	 */ 
			 | 
		
		
	
		
			
			| 
				635
			 | 
			
				651
			 | 
			
			
				
				 	chap_set_identifier ( &iscsi->chap, identifier ); 
			 | 
		
		
	
		
			
			| 
				636
			 | 
			
				
			 | 
			
			
				
				-	if ( iscsi->password ) { 
			 | 
		
		
	
		
			
			| 
				637
			 | 
			
				
			 | 
			
			
				
				-		chap_update ( &iscsi->chap, iscsi->password, 
			 | 
		
		
	
		
			
			| 
				638
			 | 
			
				
			 | 
			
			
				
				-			      strlen ( iscsi->password ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				652
			 | 
			
			
				
				+	if ( iscsi_password ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				653
			 | 
			
			
				
				+		chap_update ( &iscsi->chap, iscsi_password, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				654
			 | 
			
			
				
				+			      strlen ( iscsi_password ) ); 
			 | 
		
		
	
		
			
			| 
				639
			 | 
			
				655
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				640
			 | 
			
				656
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				641
			 | 
			
				657
			 | 
			
			
				
				 	return 0; 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -1245,55 +1261,275 @@ static struct xfer_interface_operations iscsi_socket_operations = { 
			 | 
		
		
	
		
			
			| 
				1245
			 | 
			
				1261
			 | 
			
			
				
				 	.deliver_raw	= iscsi_socket_deliver_raw, 
			 | 
		
		
	
		
			
			| 
				1246
			 | 
			
				1262
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				1247
			 | 
			
				1263
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1264
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1265
			 | 
			
			
				
				+/**************************************************************************** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1266
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1267
			 | 
			
			
				
				+ * iSCSI to SCSI interface 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1268
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1269
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1270
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				1248
			 | 
			
				1271
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				1249
			 | 
			
				
			 | 
			
			
				
				- * Issue SCSI command via iSCSI session 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1272
			 | 
			
			
				
				+ * Issue SCSI command 
			 | 
		
		
	
		
			
			| 
				1250
			 | 
			
				1273
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				1251
			 | 
			
				
			 | 
			
			
				
				- * @v iscsi		iSCSI session 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1274
			 | 
			
			
				
				+ * @v scsi		SCSI interface 
			 | 
		
		
	
		
			
			| 
				1252
			 | 
			
				1275
			 | 
			
			
				
				  * @v command		SCSI command 
			 | 
		
		
	
		
			
			| 
				1253
			 | 
			
				
			 | 
			
			
				
				- * @v parent		Parent asynchronous operation 
			 | 
		
		
	
		
			
			| 
				1254
			 | 
			
				1276
			 | 
			
			
				
				  * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				1255
			 | 
			
				1277
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				1256
			 | 
			
				
			 | 
			
			
				
				-int iscsi_issue ( struct iscsi_session *iscsi, struct scsi_command *command, 
			 | 
		
		
	
		
			
			| 
				1257
			 | 
			
				
			 | 
			
			
				
				-		  struct async *parent ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1278
			 | 
			
			
				
				+static int iscsi_scsi_issue ( struct scsi_interface *scsi, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1279
			 | 
			
			
				
				+			      struct scsi_command *command ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1280
			 | 
			
			
				
				+	struct iscsi_session *iscsi = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1281
			 | 
			
			
				
				+		container_of ( scsi, struct iscsi_session, scsi ); 
			 | 
		
		
	
		
			
			| 
				1258
			 | 
			
				1282
			 | 
			
			
				
				 	int rc; 
			 | 
		
		
	
		
			
			| 
				1259
			 | 
			
				1283
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				1260
			 | 
			
				
			 | 
			
			
				
				-	assert ( iscsi->command == NULL ); 
			 | 
		
		
	
		
			
			| 
				1261
			 | 
			
				
			 | 
			
			
				
				-	iscsi->command = command; 
			 | 
		
		
	
		
			
			| 
				1262
			 | 
			
				1284
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				1263
			 | 
			
				
			 | 
			
			
				
				-	if ( iscsi->instant_rc ) { 
			 | 
		
		
	
		
			
			| 
				1264
			 | 
			
				
			 | 
			
			
				
				-		/* Abort immediately rather than retrying */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1285
			 | 
			
			
				
				+	/* Abort immediately if we have a recorded permanent failure */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1286
			 | 
			
			
				
				+	if ( iscsi->instant_rc ) 
			 | 
		
		
	
		
			
			| 
				1265
			 | 
			
				1287
			 | 
			
			
				
				 		return iscsi->instant_rc; 
			 | 
		
		
	
		
			
			| 
				1266
			 | 
			
				
			 | 
			
			
				
				-	} else if ( iscsi->status ) { 
			 | 
		
		
	
		
			
			| 
				1267
			 | 
			
				
			 | 
			
			
				
				-		/* Session already open: issue command */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1288
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1289
			 | 
			
			
				
				+	/* Issue command or open connection as appropriate */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1290
			 | 
			
			
				
				+	if ( iscsi->status ) { 
			 | 
		
		
	
		
			
			| 
				1268
			 | 
			
				1291
			 | 
			
			
				
				 		iscsi_start_command ( iscsi ); 
			 | 
		
		
	
		
			
			| 
				1269
			 | 
			
				
			 | 
			
			
				
				-		stream_kick ( &iscsi->stream ); 
			 | 
		
		
	
		
			
			| 
				1270
			 | 
			
				1292
			 | 
			
			
				
				 	} 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 ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1293
			 | 
			
			
				
				+		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				1276
			 | 
			
				1294
			 | 
			
			
				
				 			return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1295
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1296
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1297
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1298
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1299
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1300
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1301
			 | 
			
			
				
				+ * Detach SCSI interface 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1302
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1303
			 | 
			
			
				
				+ * @v scsi		SCSI interface 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1304
			 | 
			
			
				
				+ * @v rc		Reason for close 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1305
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1306
			 | 
			
			
				
				+static void iscsi_scsi_detach ( struct scsi_interface *scsi, int rc ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1307
			 | 
			
			
				
				+	struct iscsi_session *iscsi = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1308
			 | 
			
			
				
				+		container_of ( scsi, struct iscsi_session, scsi ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1309
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1310
			 | 
			
			
				
				+	iscsi_close_connection ( iscsi, rc ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1311
			 | 
			
			
				
				+	process_del ( &iscsi->process ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1312
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1313
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1314
			 | 
			
			
				
				+/**************************************************************************** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1315
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1316
			 | 
			
			
				
				+ * Instantiator 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1317
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1318
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1319
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1320
			 | 
			
			
				
				+/** iSCSI root path components (as per RFC4173) */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1321
			 | 
			
			
				
				+enum iscsi_root_path_component { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1322
			 | 
			
			
				
				+	RP_LITERAL = 0, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1323
			 | 
			
			
				
				+	RP_SERVERNAME, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1324
			 | 
			
			
				
				+	RP_PROTOCOL, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1325
			 | 
			
			
				
				+	RP_PORT, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1326
			 | 
			
			
				
				+	RP_LUN, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1327
			 | 
			
			
				
				+	RP_TARGETNAME, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1328
			 | 
			
			
				
				+	NUM_RP_COMPONENTS 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1329
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1330
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1331
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1332
			 | 
			
			
				
				+ * Parse iSCSI LUN 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1333
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1334
			 | 
			
			
				
				+ * @v iscsi		iSCSI session 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1335
			 | 
			
			
				
				+ * @v lun_string	LUN string representation (as per RFC4173) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1336
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1337
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1338
			 | 
			
			
				
				+static int iscsi_parse_lun ( struct iscsi_session *iscsi, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1339
			 | 
			
			
				
				+			     const char *lun_string ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1340
			 | 
			
			
				
				+	char *p = ( char * ) lun_string; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1341
			 | 
			
			
				
				+	union { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1342
			 | 
			
			
				
				+		uint64_t u64; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1343
			 | 
			
			
				
				+		uint16_t u16[4]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1344
			 | 
			
			
				
				+	} lun; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1345
			 | 
			
			
				
				+	int i; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1346
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1347
			 | 
			
			
				
				+	for ( i = 0 ; i < 4 ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1348
			 | 
			
			
				
				+		lun.u16[i] = strtoul ( p, &p, 16 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1349
			 | 
			
			
				
				+		if ( *p != '-' ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1350
			 | 
			
			
				
				+			return -EINVAL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1351
			 | 
			
			
				
				+		p++; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1352
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1353
			 | 
			
			
				
				+	if ( *p ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1354
			 | 
			
			
				
				+		return -EINVAL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1355
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1356
			 | 
			
			
				
				+	iscsi->lun = lun.u64; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1357
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1358
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1359
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1360
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1361
			 | 
			
			
				
				+ * Parse iSCSI root path 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1362
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1363
			 | 
			
			
				
				+ * @v iscsi		iSCSI session 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1364
			 | 
			
			
				
				+ * @v root_path		iSCSI root path (as per RFC4173) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1365
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1366
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1367
			 | 
			
			
				
				+static int iscsi_parse_root_path ( struct iscsi_session *iscsi, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1368
			 | 
			
			
				
				+				   const char *root_path ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1369
			 | 
			
			
				
				+	const char *p = root_path; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1370
			 | 
			
			
				
				+	char *fragment; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1371
			 | 
			
			
				
				+	size_t len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1372
			 | 
			
			
				
				+	enum iscsi_root_path_component i; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1373
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1374
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1375
			 | 
			
			
				
				+	for ( i = 0 ; i < NUM_RP_COMPONENTS ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1376
			 | 
			
			
				
				+		len = strcspn ( p, ":" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1377
			 | 
			
			
				
				+		fragment = strndup ( p, len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1378
			 | 
			
			
				
				+		if ( ! fragment ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1379
			 | 
			
			
				
				+			DBGC ( iscsi, "iSCSI %p could not duplicate root " 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1380
			 | 
			
			
				
				+			       "path component at %s\n", iscsi, p ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1381
			 | 
			
			
				
				+			return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				1277
			 | 
			
				1382
			 | 
			
			
				
				 		} 
			 | 
		
		
	
		
			
			| 
				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; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1383
			 | 
			
			
				
				+		switch ( i ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1384
			 | 
			
			
				
				+		case RP_SERVERNAME: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1385
			 | 
			
			
				
				+			iscsi->target_address = fragment; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1386
			 | 
			
			
				
				+			break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1387
			 | 
			
			
				
				+		case RP_PORT: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1388
			 | 
			
			
				
				+			iscsi->target_port = strtoul ( fragment, NULL, 10 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1389
			 | 
			
			
				
				+			if ( ! iscsi->target_port ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1390
			 | 
			
			
				
				+				iscsi->target_port = ISCSI_PORT; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1391
			 | 
			
			
				
				+			free ( fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1392
			 | 
			
			
				
				+			break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1393
			 | 
			
			
				
				+		case RP_LUN: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1394
			 | 
			
			
				
				+			rc = iscsi_parse_lun ( iscsi, fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1395
			 | 
			
			
				
				+			free ( fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1396
			 | 
			
			
				
				+			if ( rc != 0 ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1397
			 | 
			
			
				
				+				DBGC ( iscsi, "iSCSI %p invalid LUN %s\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1398
			 | 
			
			
				
				+				       iscsi, fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1399
			 | 
			
			
				
				+				return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1400
			 | 
			
			
				
				+			} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1401
			 | 
			
			
				
				+			break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1402
			 | 
			
			
				
				+		case RP_TARGETNAME: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1403
			 | 
			
			
				
				+			iscsi->target_iqn = fragment; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1404
			 | 
			
			
				
				+			break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1405
			 | 
			
			
				
				+		default: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1406
			 | 
			
			
				
				+			free ( fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1407
			 | 
			
			
				
				+			break; 
			 | 
		
		
	
		
			
			| 
				1283
			 | 
			
				1408
			 | 
			
			
				
				 		} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1409
			 | 
			
			
				
				+		p += len; 
			 | 
		
		
	
		
			
			| 
				1284
			 | 
			
				1410
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				1285
			 | 
			
				1411
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				1286
			 | 
			
				
			 | 
			
			
				
				-	async_init ( &iscsi->async, &default_async_operations, parent ); 
			 | 
		
		
	
		
			
			| 
				1287
			 | 
			
				1412
			 | 
			
			
				
				 	return 0; 
			 | 
		
		
	
		
			
			| 
				1288
			 | 
			
				1413
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				1289
			 | 
			
				1414
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				1290
			 | 
			
				1415
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				1291
			 | 
			
				
			 | 
			
			
				
				- * Close down iSCSI session 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1416
			 | 
			
			
				
				+ * Attach iSCSI interface 
			 | 
		
		
	
		
			
			| 
				1292
			 | 
			
				1417
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				1293
			 | 
			
				
			 | 
			
			
				
				- * @v iscsi		iSCSI session 
			 | 
		
		
	
		
			
			| 
				1294
			 | 
			
				
			 | 
			
			
				
				- * @ret aop		Asynchronous operation 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1418
			 | 
			
			
				
				+ * @v scsi		SCSI interface 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1419
			 | 
			
			
				
				+ * @v root_path		iSCSI root path (as per RFC4173) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1420
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				1295
			 | 
			
				1421
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				1296
			 | 
			
				
			 | 
			
			
				
				-void iscsi_shutdown ( struct iscsi_session *iscsi ) { 
			 | 
		
		
	
		
			
			| 
				1297
			 | 
			
				
			 | 
			
			
				
				-	iscsi_close_connection ( iscsi, 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1422
			 | 
			
			
				
				+int iscsi_attach ( struct scsi_interface *scsi, const char *root_path ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1423
			 | 
			
			
				
				+	struct iscsi_session *iscsi; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1424
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1425
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1426
			 | 
			
			
				
				+	/* Allocate and initialise structure */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1427
			 | 
			
			
				
				+	iscsi = zalloc ( sizeof ( *iscsi ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1428
			 | 
			
			
				
				+	if ( ! iscsi ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1429
			 | 
			
			
				
				+		return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1430
			 | 
			
			
				
				+	xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1431
			 | 
			
			
				
				+	process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1432
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1433
			 | 
			
			
				
				+	/* Parse root path */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1434
			 | 
			
			
				
				+	if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1435
			 | 
			
			
				
				+		goto err; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1436
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1437
			 | 
			
			
				
				+	/* Sanity checks */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1438
			 | 
			
			
				
				+	if ( ! iscsi->target_address ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1439
			 | 
			
			
				
				+		DBGC ( iscsi, "iSCSI %p does not yet support discovery\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1440
			 | 
			
			
				
				+		       iscsi ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1441
			 | 
			
			
				
				+		rc = -ENOTSUP; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1442
			 | 
			
			
				
				+		goto err; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1443
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1444
			 | 
			
			
				
				+	if ( ! iscsi->target_iqn ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1445
			 | 
			
			
				
				+		DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1446
			 | 
			
			
				
				+		       iscsi, root_path ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1447
			 | 
			
			
				
				+		rc = -EINVAL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1448
			 | 
			
			
				
				+		goto err; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1449
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1450
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1451
			 | 
			
			
				
				+	/* Attach parent interface, mortalise self, and return */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1452
			 | 
			
			
				
				+	scsi_plug_plug ( &iscsi->scsi, scsi ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1453
			 | 
			
			
				
				+	ref_put ( &iscsi->refcnt ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1454
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1455
			 | 
			
			
				
				+	 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1456
			 | 
			
			
				
				+ err: 
			 | 
		
		
	
		
			
			| 
				1298
			 | 
			
				1457
			 | 
			
			
				
				 	ref_put ( &iscsi->refcnt ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1458
			 | 
			
			
				
				+	return rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1459
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1460
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1461
			 | 
			
			
				
				+/**************************************************************************** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1462
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1463
			 | 
			
			
				
				+ * DHCP option applicators 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1464
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1465
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1466
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1467
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1468
			 | 
			
			
				
				+ * Apply DHCP iSCSI option 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1469
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1470
			 | 
			
			
				
				+ * @v tag		DHCP option tag 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1471
			 | 
			
			
				
				+ * @v option		DHCP option 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1472
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1473
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1474
			 | 
			
			
				
				+static int apply_dhcp_iscsi_string ( unsigned int tag, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1475
			 | 
			
			
				
				+				     struct dhcp_option *option ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1476
			 | 
			
			
				
				+	char *prefix = ""; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1477
			 | 
			
			
				
				+	size_t prefix_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1478
			 | 
			
			
				
				+	size_t len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1479
			 | 
			
			
				
				+	char **string; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1480
			 | 
			
			
				
				+	char *p; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1481
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1482
			 | 
			
			
				
				+	/* Identify string and prefix */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1483
			 | 
			
			
				
				+	switch ( tag ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1484
			 | 
			
			
				
				+	case DHCP_ISCSI_INITIATOR_IQN: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1485
			 | 
			
			
				
				+		string = &iscsi_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1486
			 | 
			
			
				
				+		break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1487
			 | 
			
			
				
				+	case DHCP_EB_USERNAME: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1488
			 | 
			
			
				
				+		string = &iscsi_username; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1489
			 | 
			
			
				
				+		break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1490
			 | 
			
			
				
				+	case DHCP_EB_PASSWORD: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1491
			 | 
			
			
				
				+		string = &iscsi_password; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1492
			 | 
			
			
				
				+		break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1493
			 | 
			
			
				
				+	case DHCP_HOST_NAME: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1494
			 | 
			
			
				
				+		string = &iscsi_default_initiator_iqn; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1495
			 | 
			
			
				
				+		prefix = "iqn.2000-09.org.etherboot:"; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1496
			 | 
			
			
				
				+		break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1497
			 | 
			
			
				
				+	default: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1498
			 | 
			
			
				
				+		assert ( 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1499
			 | 
			
			
				
				+		return -EINVAL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1500
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1501
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1502
			 | 
			
			
				
				+	/* Free old string */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1503
			 | 
			
			
				
				+	free ( *string ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1504
			 | 
			
			
				
				+	*string = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1505
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1506
			 | 
			
			
				
				+	/* Allocate and fill new string */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1507
			 | 
			
			
				
				+	prefix_len = strlen ( prefix ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1508
			 | 
			
			
				
				+	len = ( prefix_len + option->len + 1 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1509
			 | 
			
			
				
				+	p = *string = malloc ( len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1510
			 | 
			
			
				
				+	if ( ! p ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1511
			 | 
			
			
				
				+		return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1512
			 | 
			
			
				
				+	strcpy ( p, prefix ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1513
			 | 
			
			
				
				+	dhcp_snprintf ( ( p + prefix_len ), ( len - prefix_len ), option ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1514
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				1299
			 | 
			
				1515
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1516
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1517
			 | 
			
			
				
				+/** DHCP iSCSI option applicators */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1518
			 | 
			
			
				
				+struct dhcp_option_applicator dhcp_iscsi_applicators[] __dhcp_applicator = { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1519
			 | 
			
			
				
				+	{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1520
			 | 
			
			
				
				+		.tag = DHCP_ISCSI_INITIATOR_IQN, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1521
			 | 
			
			
				
				+		.apply = apply_dhcp_iscsi_string, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1522
			 | 
			
			
				
				+	}, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1523
			 | 
			
			
				
				+	{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1524
			 | 
			
			
				
				+		.tag = DHCP_EB_USERNAME, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1525
			 | 
			
			
				
				+		.apply = apply_dhcp_iscsi_string, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1526
			 | 
			
			
				
				+	}, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1527
			 | 
			
			
				
				+	{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1528
			 | 
			
			
				
				+		.tag = DHCP_EB_PASSWORD, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1529
			 | 
			
			
				
				+		.apply = apply_dhcp_iscsi_string, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1530
			 | 
			
			
				
				+	}, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1531
			 | 
			
			
				
				+	{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1532
			 | 
			
			
				
				+		.tag = DHCP_HOST_NAME, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1533
			 | 
			
			
				
				+		.apply = apply_dhcp_iscsi_string, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1534
			 | 
			
			
				
				+	}, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				1535
			 | 
			
			
				
				+}; 
			 |