Blame SOURCES/0007-URL-encoded-Targetnames.patch

a66d21
From e061cba1b91650ab08ae8fa50e8cadb13ac3d97d Mon Sep 17 00:00:00 2001
a66d21
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
a66d21
Date: Sun, 16 Jun 2013 11:35:14 -0700
a66d21
Subject: [RHEL7 libiscsi PATCH 07/18] URL encoded Targetnames
a66d21
a66d21
Assume target names are URL encoded with '%' as the special character.
a66d21
a66d21
Any sequence of '%' followed by two bytes in the target name will be replaced
a66d21
with the byte that the second two bytes represent in hexadecimal.
a66d21
a66d21
Example
a66d21
iqn.ronnie.test%3A1234
a66d21
will be translated to iqn.ronnie.test:1234
a66d21
a66d21
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
a66d21
(cherry-picked from upstream commit e061cba1b91650ab08ae8fa50e8cadb13ac3d97d)
a66d21
a66d21
[The right thing to do here is probably to not use this simple-minded code
a66d21
 and use QEMU's URI parser.  I need to find a testcase, then I will create
a66d21
 a bug. - Paolo]
a66d21
---
a66d21
 include/iscsi.h |  12 ++++--
a66d21
 lib/init.c      | 114 +++++++++++++++++++++++++++++++++++++++-----------------
a66d21
 lib/login.c     |   1 +
a66d21
 3 files changed, 88 insertions(+), 39 deletions(-)
a66d21
a66d21
diff --git a/include/iscsi.h b/include/iscsi.h
a66d21
index f14d404..a4ed932 100644
a66d21
--- a/include/iscsi.h
a66d21
+++ b/include/iscsi.h
a66d21
@@ -125,6 +125,10 @@ iscsi_set_initial_r2t(struct iscsi_context *iscsi, enum iscsi_initial_r2t initia
a66d21
  * iSCSI URL format :
a66d21
  * iscsi://[<username>[%<password>]@]<host>[:<port>]/<target-iqn>/<lun>
a66d21
  *
a66d21
+ * Target names are url encoded with '%' as a special character.
a66d21
+ * Example:
a66d21
+ * "iqn.ronnie.test%3A1234" will be translated to "iqn.ronnie.test:1234"
a66d21
+ *
a66d21
  * Function will return a pointer to an iscsi url structure if successful,
a66d21
  * or it will return NULL and set iscsi_get_error() accrodingly if there was a problem
a66d21
  * with the URL.
a66d21
diff --git a/lib/init.c b/lib/init.c
a66d21
index 18f3fb2..60a1b6d 100644
a66d21
--- a/lib/init.c
a66d21
+++ b/lib/init.c
a66d21
@@ -358,6 +358,45 @@ iscsi_is_logged_in(struct iscsi_context *iscsi)
a66d21
 	return iscsi->is_loggedin;
a66d21
 }
a66d21
 
a66d21
+static int
a66d21
+h2i(int h)
a66d21
+{
a66d21
+	if (h >= 'a' && h <= 'f') {
a66d21
+		return h - 'a' + 10;
a66d21
+	}
a66d21
+	if (h >= 'A' && h <= 'F') {
a66d21
+		return h - 'A' + 10;
a66d21
+	}
a66d21
+	return h - '0';
a66d21
+}
a66d21
+
a66d21
+static void
a66d21
+iscsi_decode_url_string(char *str)
a66d21
+{
a66d21
+	while (*str) {
a66d21
+		char *tmp = str;
a66d21
+		char c;
a66d21
+
a66d21
+		if (*str++ != '%') {
a66d21
+			continue;
a66d21
+		}
a66d21
+
a66d21
+		if (*str == 0) {
a66d21
+			return;
a66d21
+		}
a66d21
+		c = h2i(*str++) << 4;
a66d21
+
a66d21
+		if (*str == 0) {
a66d21
+			return;
a66d21
+		}
a66d21
+		c |= h2i(*str++);
a66d21
+
a66d21
+		*tmp++ = c;
a66d21
+		memmove(tmp, str, strlen(str));
a66d21
+		tmp[strlen(str)] = 0;
a66d21
+	}
a66d21
+}
a66d21
+
a66d21
 struct iscsi_url *
a66d21
 iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
a66d21
 {
a66d21
@@ -373,15 +412,18 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
a66d21
 
a66d21
 	if (strncmp(url, "iscsi://", 8)) {
a66d21
 		if (full) {
a66d21
-		iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must be of "
a66d21
-				"the form: %s",url,ISCSI_URL_SYNTAX); }
a66d21
-		else {
a66d21
-		iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal URL must be of "
a66d21
-				"the form: %s",url,ISCSI_PORTAL_URL_SYNTAX); }
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must "
a66d21
+				"be of the form: %s",
a66d21
+				url, ISCSI_URL_SYNTAX);
a66d21
+		} else {
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal "
a66d21
+				"URL must be of the form: %s",
a66d21
+				url, ISCSI_PORTAL_URL_SYNTAX);
a66d21
+		}
a66d21
 		return NULL;
a66d21
 	}
a66d21
 
a66d21
-	strncpy(str,url + 8,MAX_STRING_SIZE);
a66d21
+	strncpy(str,url + 8, MAX_STRING_SIZE);
a66d21
 	portal = str;
a66d21
 
a66d21
 	user   = getenv("LIBISCSI_CHAP_USERNAME");
a66d21
@@ -406,56 +448,56 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
a66d21
 	if (full) {
a66d21
 		target = strchr(portal, '/');
a66d21
 		if (target == NULL) {
a66d21
-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
a66d21
-				"'<target-iqn>'\niSCSI URL must be of the "
a66d21
-				"form: %s",
a66d21
-				url,
a66d21
-				ISCSI_URL_SYNTAX);
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
a66d21
+				"parse '<target-iqn>'\niSCSI URL must be of "
a66d21
+				"the form: %s",
a66d21
+				url, ISCSI_URL_SYNTAX);
a66d21
 			return NULL;
a66d21
 		}
a66d21
 		*target++ = 0;
a66d21
 
a66d21
 		if (*target == 0) {
a66d21
-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
a66d21
-				"<target-iqn>\n"
a66d21
-				"iSCSI URL must be of the form: %s",
a66d21
-				url,
a66d21
-				ISCSI_URL_SYNTAX);
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
a66d21
+				"parse <target-iqn>\niSCSI URL must be of the "
a66d21
+				"form: %s",
a66d21
+				url, ISCSI_URL_SYNTAX);
a66d21
 			return NULL;
a66d21
 		}
a66d21
 
a66d21
 		lun = strchr(target, '/');
a66d21
 		if (lun == NULL) {
a66d21
-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
a66d21
-				"iSCSI URL must be of the form: %s",
a66d21
-				url,
a66d21
-				ISCSI_URL_SYNTAX);
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
a66d21
+				"parse <lun>\niSCSI URL must be of the form: "
a66d21
+				"%s",
a66d21
+				url, ISCSI_URL_SYNTAX);
a66d21
 			return NULL;
a66d21
 		}
a66d21
 		*lun++ = 0;
a66d21
 
a66d21
 		l = strtol(lun, &tmp, 10);
a66d21
 		if (*lun == 0 || *tmp != 0) {
a66d21
-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
a66d21
-				"iSCSI URL must be of the form: %s",
a66d21
-				url,
a66d21
-				ISCSI_URL_SYNTAX);
a66d21
+			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
a66d21
+				"parse <lun>\niSCSI URL must be of the form: "
a66d21
+				"%s",
a66d21
+				url, ISCSI_URL_SYNTAX);
a66d21
 			return NULL;
a66d21
 		}
a66d21
-	}
a66d21
-	else
a66d21
-	{
a66d21
+	} else {
a66d21
 		tmp=strchr(portal,'/');
a66d21
-		if (tmp) *tmp=0;
a66d21
+		if (tmp) {
a66d21
+			*tmp=0;
a66d21
+		}
a66d21
 	}
a66d21
 	
a66d21
-	if (iscsi != NULL)
a66d21
+	if (iscsi != NULL) {
a66d21
 		iscsi_url = iscsi_malloc(iscsi, sizeof(struct iscsi_url));
a66d21
-	else
a66d21
+	} else {
a66d21
 		iscsi_url = malloc(sizeof(struct iscsi_url));
a66d21
-	
a66d21
+	}
a66d21
+
a66d21
 	if (iscsi_url == NULL) {
a66d21
-		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate iscsi_url structure");
a66d21
+		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
a66d21
+			"iscsi_url structure");
a66d21
 		return NULL;
a66d21
 	}
a66d21
 	memset(iscsi_url, 0, sizeof(struct iscsi_url));
a66d21
@@ -464,15 +506,17 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
a66d21
 	strncpy(iscsi_url->portal,portal,MAX_STRING_SIZE);
a66d21
 
a66d21
 	if (user != NULL && passwd != NULL) {
a66d21
-		strncpy(iscsi_url->user,user,MAX_STRING_SIZE);
a66d21
-		strncpy(iscsi_url->passwd,passwd,MAX_STRING_SIZE);
a66d21
+		strncpy(iscsi_url->user, user, MAX_STRING_SIZE);
a66d21
+		strncpy(iscsi_url->passwd, passwd, MAX_STRING_SIZE);
a66d21
 	}
a66d21
 
a66d21
 	if (full) {
a66d21
-		strncpy(iscsi_url->target,target,MAX_STRING_SIZE);
a66d21
+		strncpy(iscsi_url->target, target, MAX_STRING_SIZE);
a66d21
 		iscsi_url->lun = l;
a66d21
 	}
a66d21
 
a66d21
+	iscsi_decode_url_string(&iscsi_url->target[0]);
a66d21
+
a66d21
 	return iscsi_url;
a66d21
 }
a66d21
 
a66d21
diff --git a/lib/login.c b/lib/login.c
a66d21
index 29fe4b3..0448ce2 100644
a66d21
--- a/lib/login.c
a66d21
+++ b/lib/login.c
a66d21
@@ -622,6 +622,7 @@ h2i(int h)
a66d21
 	}
a66d21
 	return h - '0';
a66d21
 }
a66d21
+
a66d21
 static int
a66d21
 i2h(int i)
a66d21
 {
a66d21
-- 
a66d21
1.8.1.4
a66d21