diff mbox series

[RFC,27/48] target: core: fix parsing PR OUT TID

Message ID 20220803162857.27770-28-d.bogdanov@yadro.com
State New
Headers show
Series Target cluster implementation over DLM | expand

Commit Message

Dmitry Bogdanov June 29, 2022, 7:50 a.m. UTC
Now only iSCSI TransportID is parsed. From other protocols the binary
representation is passed to tcm core. That is wrong as that TID is
compared against nacl->initiatorname which is in human readable format.
This patch adds a parsing of TID for other protocols.

Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
---
 drivers/target/target_core_fabric_lib.c | 119 ++++++++++++++++--------
 drivers/target/target_core_internal.h   |   4 +-
 drivers/target/target_core_pr.c         |  14 ++-
 3 files changed, 89 insertions(+), 48 deletions(-)
diff mbox series

Patch

diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c
index 32c2afbb3033..34fdab558e24 100644
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -214,15 +214,67 @@  static int iscsi_get_pr_transport_id(
 	return len;
 }
 
-static char *iscsi_parse_pr_out_transport_id(
-	struct se_portal_group *se_tpg,
-	char *buf,
-	u32 *out_tid_len,
+static u32 sas_parse_pr_out_transport_id(
+	const char *buf,
+	char *initiatorname,
+	char **port_nexus_ptr)
+{
+	char port_name[17];
+
+	bin2hex(port_name, buf + 4, 8);
+	snprintf(initiatorname, 36, "naa.%s", port_name);
+
+	return 24;
+}
+
+
+static u32 sbp_parse_pr_out_transport_id(
+	const char *buf,
+	char *initiatorname,
+	char **port_nexus_ptr)
+{
+	bin2hex(initiatorname, buf + 8, 8);
+
+	return 24;
+}
+
+static u32 srp_parse_pr_out_transport_id(
+	const char *buf,
+	char *initiatorname,
+	char **port_nexus_ptr)
+{
+	char port_name[33];
+
+	bin2hex(port_name, buf + 8, 16);
+	snprintf(initiatorname, 36, "0x%s", port_name);
+
+	return 24;
+}
+
+static u32 fc_parse_pr_out_transport_id(
+	const char *buf,
+	char *initiatorname,
+	char **port_nexus_ptr)
+{
+	/*
+	 * Format the FCP Initiator port_name into colon separated values to
+	 * match the format by tcm_qla2xxx explicit ConfigFS NodeACLs.
+	 */
+	snprintf(initiatorname, 36, "%8phC", buf + 8);
+
+	return 24;
+}
+
+u32 iscsi_parse_pr_out_transport_id(
+	const char *buf,
+	char *initiatorname,
 	char **port_nexus_ptr)
 {
 	char *p;
 	int i;
 	u8 format_code = (buf[0] & 0xc0);
+	u32 out_tid_len;
+
 	/*
 	 * Check for FORMAT CODE 00b or 01b from spc4r17, section 7.5.4.6:
 	 *
@@ -239,18 +291,10 @@  static char *iscsi_parse_pr_out_transport_id(
 	if ((format_code != 0x00) && (format_code != 0x40)) {
 		pr_err("Illegal format code: 0x%02x for iSCSI"
 			" Initiator Transport ID\n", format_code);
-		return NULL;
-	}
-	/*
-	 * If the caller wants the TransportID Length, we set that value for the
-	 * entire iSCSI Tarnsport ID now.
-	 */
-	if (out_tid_len) {
-		/* The shift works thanks to integer promotion rules */
-		*out_tid_len = get_unaligned_be16(&buf[2]);
-		/* Add four bytes for iSCSI Transport ID header */
-		*out_tid_len += 4;
+		return 0;
 	}
+	/* The shift works thanks to integer promotion rules */
+	out_tid_len = get_unaligned_be16(&buf[2]);
 
 	/*
 	 * Check for ',i,0x' separator between iSCSI Name and iSCSI Initiator
@@ -263,9 +307,10 @@  static char *iscsi_parse_pr_out_transport_id(
 			pr_err("Unable to locate \",i,0x\" separator"
 				" for Initiator port identifier: %s\n",
 				&buf[4]);
-			return NULL;
+			return 0;
 		}
-		*p = '\0'; /* Terminate iSCSI Name */
+		memcpy(initiatorname, &buf[4], p - buf - 4);
+		initiatorname[p - buf - 4] = '\0'; /* Terminate iSCSI Name */
 		p += 5; /* Skip over ",i,0x" separator */
 
 		*port_nexus_ptr = p;
@@ -293,10 +338,16 @@  static char *iscsi_parse_pr_out_transport_id(
 			*p = tolower(*p);
 			p++;
 		}
-	} else
+	} else {
+		strscpy(initiatorname, &buf[4], out_tid_len);
+		initiatorname[p - buf] = '\0'; /* Terminate iSCSI Name */
 		*port_nexus_ptr = NULL;
+	}
+
+	/* Add four bytes for iSCSI Transport ID header */
+	out_tid_len += 4;
 
-	return &buf[4];
+	return out_tid_len;
 }
 
 int target_get_pr_transport_id_len(struct t10_pr_registration *pr_reg)
@@ -351,33 +402,25 @@  int target_gen_pr_transport_id(
 	}
 }
 
-const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
-		char *buf, u32 *out_tid_len, char **port_nexus_ptr)
+u32 target_parse_pr_out_transport_id(
+	const char *buf, char *initiatorname, char **port_nexus_ptr)
 {
-	u32 offset;
-
-	switch (tpg->proto_id) {
+	switch (buf[0] & 0xF) {
 	case SCSI_PROTOCOL_SAS:
-		/*
-		 * Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
-		 * for initiator ports using SCSI over SAS Serial SCSI Protocol.
-		 */
-		offset = 4;
-		break;
+		return sas_parse_pr_out_transport_id(buf, initiatorname, port_nexus_ptr);
 	case SCSI_PROTOCOL_SBP:
+		return sbp_parse_pr_out_transport_id(buf, initiatorname, port_nexus_ptr);
 	case SCSI_PROTOCOL_SRP:
+		return srp_parse_pr_out_transport_id(buf, initiatorname, port_nexus_ptr);
 	case SCSI_PROTOCOL_FCP:
-		offset = 8;
-		break;
+		return fc_parse_pr_out_transport_id(buf, initiatorname, port_nexus_ptr);
 	case SCSI_PROTOCOL_ISCSI:
-		return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
-					port_nexus_ptr);
+		return iscsi_parse_pr_out_transport_id(buf, initiatorname, port_nexus_ptr);
 	default:
-		pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
-		return NULL;
+		pr_err("Unknown proto_id: 0x%02x\n", buf[0] & 0xF);
+		return 0;
 	}
 
 	*port_nexus_ptr = NULL;
-	*out_tid_len = 24;
-	return buf + offset;
+	return 24;
 }
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 51c0151c05c2..bbdddcd83fa4 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -105,8 +105,8 @@  int target_gen_pr_transport_id(struct t10_pr_registration *pr_reg,
 			       int proto_id,
 			       const char *initiatorname,
 			       unsigned char *isid);
-const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
-		char *buf, u32 *out_tid_len, char **port_nexus_ptr);
+u32 target_parse_pr_out_transport_id(
+	const char *buf, char *initiatorname, char **port_nexus_ptr);
 
 /* target_core_hba.c */
 struct se_hba *core_alloc_hba(const char *, u32, u32);
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index c4ee6999cf96..f5796d60ed76 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1419,7 +1419,7 @@  core_scsi3_decode_spec_i_port(
 	LIST_HEAD(tid_dest_list);
 	struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
 	unsigned char *buf, *ptr, proto_ident;
-	const unsigned char *i_str = NULL;
+	unsigned char i_str[TRANSPORT_IQN_LEN] = {0};
 	char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
 	sense_reason_t ret;
 	u32 tpdl, tid_len = 0;
@@ -1512,9 +1512,8 @@  core_scsi3_decode_spec_i_port(
 			dest_rtpi = tmp_lun->lun_tpg->tpg_rtpi;
 
 			iport_ptr = NULL;
-			i_str = target_parse_pr_out_transport_id(tmp_tpg,
-					ptr, &tid_len, &iport_ptr);
-			if (!i_str)
+			tid_len = target_parse_pr_out_transport_id(ptr, i_str, &iport_ptr);
+			if (!tid_len)
 				continue;
 			/*
 			 * Determine if this SCSI device server requires that
@@ -3087,7 +3086,7 @@  core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
 	struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
 	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char *buf;
-	const unsigned char *initiator_str;
+	unsigned char initiator_str[TRANSPORT_IQN_LEN] = { };
 	char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { };
 	u32 tid_len, tmp_tid_len;
 	int new_reg = 0, type, scope, matching_iname;
@@ -3212,9 +3211,8 @@  core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
 		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
-	initiator_str = target_parse_pr_out_transport_id(dest_se_tpg,
-			&buf[24], &tmp_tid_len, &iport_ptr);
-	if (!initiator_str) {
+	tmp_tid_len = target_parse_pr_out_transport_id(&buf[24], initiator_str, &iport_ptr);
+	if (!tmp_tid_len) {
 		pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
 			" initiator_str from Transport ID\n");
 		ret = TCM_INVALID_PARAMETER_LIST;