diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4d146de
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/libiscsi-1.9.0.tar.gz
diff --git a/.libiscsi.metadata b/.libiscsi.metadata
new file mode 100644
index 0000000..0285945
--- /dev/null
+++ b/.libiscsi.metadata
@@ -0,0 +1 @@
+be8bef44cc448c989e11a56c061ebea11830159f SOURCES/libiscsi-1.9.0.tar.gz
diff --git a/SOURCES/0001-do-not-reconnect-if-reconnect-is-already-defered.patch b/SOURCES/0001-do-not-reconnect-if-reconnect-is-already-defered.patch
new file mode 100644
index 0000000..dff9a92
--- /dev/null
+++ b/SOURCES/0001-do-not-reconnect-if-reconnect-is-already-defered.patch
@@ -0,0 +1,36 @@
+From 327b51ed5b2bdf0a4fc0b50a9cdd8c1f4993e49a Mon Sep 17 00:00:00 2001
+From: Peter Lieven <pl@kamp.de>
+Date: Mon, 11 Mar 2013 08:44:11 +0100
+Subject: [RHEL7 libiscsi PATCH 01/18] do not reconnect if reconnect is already defered
+
+If the amount of reconnects is limited with iscsi_set_reconnect_max_retries()
+it might happen that iscsi_reconnect is called while there is already a deferred
+reconnect.
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 327b51ed5b2bdf0a4fc0b50a9cdd8c1f4993e49a)
+---
+ lib/connect.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/lib/connect.c b/lib/connect.c
+index 86a60f8..d3fa9d1 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -219,6 +219,12 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
+ {
+ 	struct iscsi_context *iscsi = old_iscsi;
+ 
++	/* if there is already a deferred reconnect do not try again */
++	if (iscsi->reconnect_deferred) {
++		ISCSI_LOG(iscsi, 2, "reconnect initiated, but reconnect is already deferred");
++		return -1;
++	}
++
+ 	ISCSI_LOG(iscsi, 2, "reconnect initiated");
+ 
+ 	/* This is mainly for tests, where we do not want to automatically
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch b/SOURCES/0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch
new file mode 100644
index 0000000..160711b
--- /dev/null
+++ b/SOURCES/0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch
@@ -0,0 +1,31 @@
+From 5a94d5d73a18369e6f7b7c54674dc20b9c7d0a8e Mon Sep 17 00:00:00 2001
+From: Peter Lieven <pl@kamp.de>
+Date: Mon, 11 Mar 2013 08:51:18 +0100
+Subject: [RHEL7 libiscsi PATCH 02/18] fix leak of iscsi_context in iscsi_reconnect
+
+in case the maximum number of reconnects is limited with
+iscsi_set_reconnect_max_retries() the an iscsi_context
+is leaked if the limit is exhausted.
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 5a94d5d73a18369e6f7b7c54674dc20b9c7d0a8e)
+---
+ lib/connect.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/connect.c b/lib/connect.c
+index d3fa9d1..7429496 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -277,6 +277,7 @@ try_again:
+ 	if (iscsi_full_connect_sync(iscsi, iscsi->portal, iscsi->lun) != 0) {
+ 		if (iscsi->reconnect_max_retries != -1 && retry >= iscsi->reconnect_max_retries) {
+ 			iscsi_defer_reconnect(old_iscsi);
++			iscsi_destroy_context(iscsi);
+ 			return -1;
+ 		}
+ 		int backoff=retry;
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0003-Add-ASCQ-codes-related-to-thin-provisioning.patch b/SOURCES/0003-Add-ASCQ-codes-related-to-thin-provisioning.patch
new file mode 100644
index 0000000..ee221c2
--- /dev/null
+++ b/SOURCES/0003-Add-ASCQ-codes-related-to-thin-provisioning.patch
@@ -0,0 +1,77 @@
+From 80ef1807ef0c11ec5940d5763b12f3c0d4b6d32e Mon Sep 17 00:00:00 2001
+From: Peter Lieven <pl@kamp.de>
+Date: Mon, 11 Mar 2013 12:13:42 +0100
+Subject: [RHEL7 libiscsi PATCH 03/18] Add ASCQ codes related to thin-provisioning
+
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 80ef1807ef0c11ec5940d5763b12f3c0d4b6d32e)
+---
+ include/scsi-lowlevel.h | 31 +++++++++++++++++--------------
+ lib/scsi-lowlevel.c     |  6 ++++++
+ 2 files changed, 23 insertions(+), 14 deletions(-)
+
+diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h
+index cd1abd4..07d39be 100644
+--- a/include/scsi-lowlevel.h
++++ b/include/scsi-lowlevel.h
+@@ -144,20 +144,23 @@ enum scsi_sense_key {
+ EXTERN const char *scsi_sense_key_str(int key);
+ 
+ /* ascq */
+-#define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY	0x1d00
+-#define SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE		0x2000
+-#define SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE		0x2100
+-#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB		0x2400
+-#define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED	0x2500
+-#define SCSI_SENSE_ASCQ_WRITE_PROTECTED			0x2700
+-#define SCSI_SENSE_ASCQ_BUS_RESET			0x2900
+-#define SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED      	0x2a09
+-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT		0x3a00
+-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED	0x3a01
+-#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN	0x3a02
+-#define SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE	        0x4400
+-#define SCSI_SENSE_ASCQ_MEDIUM_LOAD_OR_EJECT_FAILED     0x5300
+-#define SCSI_SENSE_ASCQ_MEDIUM_REMOVAL_PREVENTED        0x5302
++#define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY           0x1d00
++#define SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE             0x2000
++#define SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE                   0x2100
++#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB               0x2400
++#define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED         0x2500
++#define SCSI_SENSE_ASCQ_WRITE_PROTECTED                    0x2700
++#define SCSI_SENSE_ASCQ_BUS_RESET                          0x2900
++#define SCSI_SENSE_ASCQ_MODE_PARAMETERS_CHANGED            0x2a01
++#define SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED          0x2a09
++#define SCSI_SENSE_ASCQ_THIN_PROVISION_SOFT_THRES_REACHED  0x3807
++#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT                 0x3a00
++#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED     0x3a01
++#define SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN       0x3a02
++#define SCSI_SENSE_ASCQ_INQUIRY_DATA_HAS_CHANGED           0x3f03
++#define SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE            0x4400
++#define SCSI_SENSE_ASCQ_MEDIUM_LOAD_OR_EJECT_FAILED        0x5300
++#define SCSI_SENSE_ASCQ_MEDIUM_REMOVAL_PREVENTED           0x5302
+ 
+ EXTERN const char *scsi_sense_ascq_str(int ascq);
+ 
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index b6af650..b49e873 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -149,8 +149,14 @@ scsi_sense_ascq_str(int ascq)
+ 		 "MEDIUM_NOT_PRESENT-TRAY_OPEN"},
+ 		{SCSI_SENSE_ASCQ_BUS_RESET,
+ 		 "BUS_RESET"},
++		{SCSI_SENSE_ASCQ_MODE_PARAMETERS_CHANGED,
++		 "MODE PARAMETERS CHANGED"},
+ 		{SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED,
+ 		 "CAPACITY_DATA_HAS_CHANGED"},
++		{SCSI_SENSE_ASCQ_THIN_PROVISION_SOFT_THRES_REACHED,
++		 "THIN PROVISIONING SOFT THRESHOLD REACHED"},
++		{SCSI_SENSE_ASCQ_INQUIRY_DATA_HAS_CHANGED,
++		 "INQUIRY DATA HAS CHANGED"},
+ 		{SCSI_SENSE_ASCQ_INTERNAL_TARGET_FAILURE,
+ 		 "INTERNAL_TARGET_FAILURE"},
+ 		{SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY,
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch b/SOURCES/0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch
new file mode 100644
index 0000000..1be22d1
--- /dev/null
+++ b/SOURCES/0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch
@@ -0,0 +1,388 @@
+From d280ce8ad742426bebe610ebfd8559b46876f4ee Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Mon, 22 Apr 2013 22:11:53 -0700
+Subject: [RHEL7 libiscsi PATCH 04/18] Create safe 16/32/64 bit accessors for reading from the
+ datain buffer and use it throughout the scsi lowlevel file.
+
+We probably want a safe accessor for byte access to at some stage.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit d280ce8ad742426bebe610ebfd8559b46876f4ee)
+---
+ lib/scsi-lowlevel.c | 154 +++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 98 insertions(+), 56 deletions(-)
+
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index c517d57..77c0bb6 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -232,6 +232,48 @@ scsi_get_uint16(const unsigned char *c)
+ 	return ntohs(*(uint16_t *)c);
+ }
+ 
++static inline uint64_t
++task_get_uint64(struct scsi_task *task, int offset)
++{
++	if (offset <= task->datain.size - 8) {
++		const unsigned char *c = &task->datain.data[offset];
++		uint64_t val;
++
++		val = ntohl(*(uint32_t *)c);
++		val <<= 32;
++		c += 4;
++		val |= ntohl(*(uint32_t *)c);
++
++		return val;
++	} else {
++		return 0;
++	}
++}
++
++static inline uint32_t
++task_get_uint32(struct scsi_task *task, int offset)
++{
++	if (offset <= task->datain.size - 4) {
++		const unsigned char *c = &task->datain.data[offset];
++
++		return ntohl(*(uint32_t *)c);
++	} else {
++		return 0;
++	}
++}
++
++static inline uint16_t
++task_get_uint16(struct scsi_task *task, int offset)
++{
++	if (offset <= task->datain.size - 2) {
++		const unsigned char *c = &task->datain.data[offset];
++
++		return ntohs(*(uint16_t *)c);
++	} else {
++		return 0;
++	}
++}
++
+ inline void
+ scsi_set_uint64(unsigned char *c, uint64_t v)
+ {
+@@ -319,7 +361,7 @@ scsi_reportluns_datain_getfullsize(struct scsi_task *task)
+ {
+ 	uint32_t list_size;
+ 
+-	list_size = scsi_get_uint32(&task->datain.data[0]) + 8;
++	list_size = task_get_uint32(task, 0) + 8;
+ 
+ 	return list_size;
+ }
+@@ -338,7 +380,7 @@ scsi_reportluns_datain_unmarshall(struct scsi_task *task)
+ 		return NULL;
+ 	}
+ 
+-	list_size = scsi_get_uint32(&task->datain.data[0]) + 8;
++	list_size = task_get_uint32(task, 0) + 8;
+ 	if (list_size < task->datain.size) {
+ 		return NULL;
+ 	}
+@@ -352,7 +394,7 @@ scsi_reportluns_datain_unmarshall(struct scsi_task *task)
+ 
+ 	list->num = num_luns;
+ 	for (i = 0; i < num_luns; i++) {
+-		list->luns[i] = scsi_get_uint16(&task->datain.data[i*8+8]);
++		list->luns[i] = task_get_uint16(task, i * 8 + 8);
+ 	}
+ 
+ 	return list;
+@@ -442,7 +484,7 @@ scsi_readtoc_datain_getfullsize(struct scsi_task *task)
+ {
+ 	uint16_t toc_data_len;
+ 
+-	toc_data_len = scsi_get_uint16(&task->datain.data[0]) + 2;
++	toc_data_len = task_get_uint16(task, 0) + 2;
+ 
+ 	return toc_data_len;
+ }
+@@ -465,7 +507,7 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
+ 		list->desc[i].desc.toc.track
+ 			= task->datain.data[4+8*i+2];
+ 		list->desc[i].desc.toc.lba
+-			= scsi_get_uint32(&task->datain.data[4+8*i+4]);
++			= task_get_uint32(task, 4 + 8 * i + 4);
+ 		break;
+ 	case SCSI_READ_SESSION_INFO:
+ 		list->desc[i].desc.ses.adr
+@@ -475,7 +517,7 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
+ 		list->desc[i].desc.ses.first_in_last
+ 			= task->datain.data[4+8*i+2];
+ 		list->desc[i].desc.ses.lba
+-			= scsi_get_uint32(&task->datain.data[4+8*i+4]);
++			= task_get_uint32(task, 4 + 8 * i + 4);
+ 		break;
+ 	case SCSI_READ_FULL_TOC:
+ 		list->desc[i].desc.full.session
+@@ -610,22 +652,22 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
+ 		if (rc16 == NULL) {
+ 			return NULL;
+ 		}
+-		rc16->returned_lba = scsi_get_uint32(&task->datain.data[0]);
+-		rc16->returned_lba = (rc16->returned_lba << 32) | scsi_get_uint32(&task->datain.data[4]);
+-		rc16->block_length = scsi_get_uint32(&task->datain.data[8]);
++		rc16->returned_lba = task_get_uint32(task, 0);
++		rc16->returned_lba = (rc16->returned_lba << 32) | task_get_uint32(task, 4);
++		rc16->block_length = task_get_uint32(task, 8);
+ 		rc16->p_type       = (task->datain.data[12] >> 1) & 0x07;
+ 		rc16->prot_en      = task->datain.data[12] & 0x01;
+ 		rc16->p_i_exp      = (task->datain.data[13] >> 4) & 0x0f;
+ 		rc16->lbppbe       = task->datain.data[13] & 0x0f;
+ 		rc16->lbpme        = !!(task->datain.data[14] & 0x80);
+ 		rc16->lbprz        = !!(task->datain.data[14] & 0x40);
+-		rc16->lalba        = scsi_get_uint16(&task->datain.data[14]) & 0x3fff;
++		rc16->lalba        = task_get_uint16(task, 14) & 0x3fff;
+ 		return rc16;
+ 	}
+ 	case SCSI_GET_LBA_STATUS: {
+ 		struct scsi_get_lba_status *gls = scsi_malloc(task,
+ 							      sizeof(*gls));
+-		int32_t len = scsi_get_uint32(&task->datain.data[0]);
++		int32_t len = task_get_uint32(task, 0);
+ 		int i;
+ 
+ 		if (gls == NULL) {
+@@ -646,11 +688,11 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
+ 		}
+ 
+ 		for (i = 0; i < (int)gls->num_descriptors; i++) {
+-			gls->descriptors[i].lba  = scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 0]);
++			gls->descriptors[i].lba  = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 0);
+ 			gls->descriptors[i].lba <<= 32;
+- 			gls->descriptors[i].lba |= scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 4]);
++ 			gls->descriptors[i].lba |= task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 4);
+ 
+-			gls->descriptors[i].num_blocks = scsi_get_uint32(&task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 8]);
++			gls->descriptors[i].num_blocks = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 8);
+ 
+ 			gls->descriptors[i].provisioning = task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 12] & 0x0f;
+ 		}
+@@ -676,7 +718,7 @@ scsi_persistentreservein_datain_getfullsize(struct scsi_task *task)
+ {
+ 	switch (scsi_persistentreservein_sa(task)) {
+ 	case SCSI_PERSISTENT_RESERVE_READ_KEYS:
+-		return scsi_get_uint32(&task->datain.data[4]) + 8;
++		return task_get_uint32(task, 4) + 8;
+ 	case SCSI_PERSISTENT_RESERVE_READ_RESERVATION:
+ 		return 8;
+ 	case SCSI_PERSISTENT_RESERVE_REPORT_CAPABILITIES:
+@@ -696,24 +738,24 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 
+ 	switch (scsi_persistentreservein_sa(task)) {
+ 	case SCSI_PERSISTENT_RESERVE_READ_KEYS:
+-		i = scsi_get_uint32(&task->datain.data[4]);
++		i = task_get_uint32(task, 4);
+ 
+ 		rk = scsi_malloc(task, offsetof(struct scsi_persistent_reserve_in_read_keys, keys) + i);
+ 		if (rk == NULL) {
+ 			return NULL;
+ 		}
+-		rk->prgeneration      = scsi_get_uint32(&task->datain.data[0]);
+-		rk->additional_length = scsi_get_uint32(&task->datain.data[4]);
++		rk->prgeneration      = task_get_uint32(task, 0);
++		rk->additional_length = task_get_uint32(task, 4);
+ 
+ 		rk->num_keys = rk->additional_length / 8;
+ 		for (i = 0; i < (int)rk->num_keys; i++) {
+-			rk->keys[i] = scsi_get_uint64(&task->datain.data[8 + i * 8]);
++			rk->keys[i] = task_get_uint64(task, 8 + i * 8);
+ 		}
+ 		return rk;
+ 	case SCSI_PERSISTENT_RESERVE_READ_RESERVATION: {
+ 		size_t	alloc_sz;
+ 
+-		i = scsi_get_uint32(&task->datain.data[4]);
++		i = task_get_uint32(task, 4);
+ 		alloc_sz = offsetof(
+ 			struct scsi_persistent_reserve_in_read_reservation,
+ 			reserved) + i;
+@@ -723,12 +765,12 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 			return NULL;
+ 		}
+ 		memset(rr, 0, alloc_sz);
+-		rr->prgeneration = scsi_get_uint32(&task->datain.data[0]);
++		rr->prgeneration = task_get_uint32(task, 0);
+ 
+ 		if (i > 0) {
+ 			rr->reserved = 1;
+ 			rr->reservation_key =
+-				scsi_get_uint64(&task->datain.data[8]);
++				task_get_uint64(task, 8);
+ 			rr->pr_type = task->datain.data[21] & 0xff;
+ 		}
+ 
+@@ -739,14 +781,14 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 		if (rc == NULL) {
+ 			return NULL;
+ 		}
+-		rc->length         = scsi_get_uint16(&task->datain.data[0]);
++		rc->length         = task_get_uint16(task, 0);
+ 		rc->crh            = !!(task->datain.data[2] & 0x10);
+ 		rc->sip_c          = !!(task->datain.data[2] & 0x08);
+ 		rc->atp_c          = !!(task->datain.data[2] & 0x04);
+ 		rc->ptpl_c         = !!(task->datain.data[2] & 0x01);
+ 		rc->tmv            = !!(task->datain.data[3] & 0x80);
+ 		rc->allow_commands = task->datain.data[3] >> 4;
+-		rc->persistent_reservation_type_mask = scsi_get_uint16(&task->datain.data[4]);
++		rc->persistent_reservation_type_mask = task_get_uint16(task, 4);
+ 
+ 		return rc;
+ 	default:
+@@ -776,7 +818,7 @@ scsi_maintenancein_datain_getfullsize(struct scsi_task *task)
+ 
+ 	switch (scsi_maintenancein_sa(task)) {
+ 	case SCSI_REPORT_SUPPORTED_OP_CODES:
+-		return scsi_get_uint32(&task->datain.data[0]) + 4;
++		return task_get_uint32(task, 0) + 4;
+ 	default:
+ 		return -1;
+ 	}
+@@ -799,7 +841,7 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
+ 			return NULL;
+ 		}
+ 
+-		len = scsi_get_uint32(&task->datain.data[0]);
++		len = task_get_uint32(task, 0);
+ 		rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len);
+ 		if (rsoc == NULL) {
+ 			return NULL;
+@@ -900,8 +942,8 @@ scsi_readcapacity10_datain_unmarshall(struct scsi_task *task)
+ 		return NULL;
+ 	}
+ 
+-	rc10->lba        = scsi_get_uint32(&task->datain.data[0]);
+-	rc10->block_size = scsi_get_uint32(&task->datain.data[4]);
++	rc10->lba        = task_get_uint32(task, 0);
++	rc10->block_size = task_get_uint32(task, 4);
+ 
+ 	return rc10;
+ }
+@@ -972,7 +1014,7 @@ scsi_inquiry_datain_getfullsize(struct scsi_task *task)
+ 	case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
+ 	case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
+ 	case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
+-		return scsi_get_uint16(&task->datain.data[2]) + 4;
++		return task_get_uint16(task, 2) + 4;
+ 	default:
+ 		return -1;
+ 	}
+@@ -1079,7 +1120,7 @@ scsi_inquiry_unmarshall_device_identification(struct scsi_task *task)
+ {
+ 	struct scsi_inquiry_device_identification *inq = scsi_malloc(task,
+ 								     sizeof(*inq));
+-	int remaining = scsi_get_uint16(&task->datain.data[2]);
++	int remaining = task_get_uint16(task, 2);
+ 	unsigned char *dptr;
+ 
+ 	if (inq == NULL) {
+@@ -1148,17 +1189,18 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
+ 
+ 	inq->wsnz                  = task->datain.data[4] & 0x01;
+ 	inq->max_cmp               = task->datain.data[5];
+-	inq->opt_gran              = scsi_get_uint16(&task->datain.data[6]);
+-	inq->max_xfer_len          = scsi_get_uint32(&task->datain.data[8]);
+-	inq->opt_xfer_len          = scsi_get_uint32(&task->datain.data[12]);
+-	inq->max_prefetch          = scsi_get_uint32(&task->datain.data[16]);
+-	inq->max_unmap             = scsi_get_uint32(&task->datain.data[20]);
+-	inq->max_unmap_bdc         = scsi_get_uint32(&task->datain.data[24]);
+-	inq->opt_unmap_gran        = scsi_get_uint32(&task->datain.data[28]);
++	inq->opt_gran              = task_get_uint16(task, 6);
++	inq->max_xfer_len          = task_get_uint32(task, 8);
++	inq->opt_xfer_len          = task_get_uint32(task, 12);
++	inq->max_prefetch          = task_get_uint32(task, 16);
++	inq->max_unmap             = task_get_uint32(task, 20);
++	inq->max_unmap_bdc         = task_get_uint32(task, 24);
++	inq->opt_unmap_gran        = task_get_uint32(task, 28);
+ 	inq->ugavalid              = !!(task->datain.data[32]&0x80);
+-	inq->unmap_gran_align      = scsi_get_uint32(&task->datain.data[32]) & 0x7fffffff;
+-	inq->max_ws_len            = scsi_get_uint32(&task->datain.data[36]);
+-	inq->max_ws_len            = (inq->max_ws_len << 32) | scsi_get_uint32(&task->datain.data[40]);
++	inq->unmap_gran_align      = task_get_uint32(task, 32) & 0x7fffffff;
++	inq->max_ws_len            = task_get_uint32(task, 36);
++	inq->max_ws_len            = (inq->max_ws_len << 32)
++				   	| task_get_uint32(task, 40);
+ 
+ 	return inq;
+ }
+@@ -1175,7 +1217,7 @@ scsi_inquiry_unmarshall_block_device_characteristics(struct scsi_task *task)
+ 	inq->device_type           = task->datain.data[0]&0x1f;
+ 	inq->pagecode              = task->datain.data[1];
+ 
+-	inq->medium_rotation_rate  = scsi_get_uint16(&task->datain.data[4]);
++	inq->medium_rotation_rate  = task_get_uint16(task, 4);
+ 	return inq;
+ }
+ 
+@@ -2040,10 +2082,10 @@ scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *
+ 	mp->caching.demand_read_retention_priority = (task->datain.data[pos+1] >> 4) & 0x0f;
+ 	mp->caching.write_retention_priority       = task->datain.data[pos+1] & 0x0f;
+ 
+-	mp->caching.disable_prefetch_transfer_length = scsi_get_uint16(&task->datain.data[pos+2]);
+-	mp->caching.minimum_prefetch = scsi_get_uint16(&task->datain.data[pos+4]);
+-	mp->caching.maximum_prefetch = scsi_get_uint16(&task->datain.data[pos+6]);
+-	mp->caching.maximum_prefetch_ceiling = scsi_get_uint16(&task->datain.data[pos+8]);
++	mp->caching.disable_prefetch_transfer_length = task_get_uint16(task, pos + 2);
++	mp->caching.minimum_prefetch = task_get_uint16(task, pos + 4);
++	mp->caching.maximum_prefetch = task_get_uint16(task, pos + 6);
++	mp->caching.maximum_prefetch_ceiling = task_get_uint16(task, pos + 8);
+ 
+ 	mp->caching.fsw    = task->datain.data[pos+10] & 0x80;
+ 	mp->caching.lbcss  = task->datain.data[pos+10] & 0x40;
+@@ -2051,7 +2093,7 @@ scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *
+ 	mp->caching.nv_dis = task->datain.data[pos+10] & 0x01;
+ 
+ 	mp->caching.number_of_cache_segments = task->datain.data[pos+11];
+-	mp->caching.cache_segment_size = scsi_get_uint16(&task->datain.data[pos+12]);
++	mp->caching.cache_segment_size = task_get_uint16(task, pos + 12);
+ }
+ 
+ static void
+@@ -2059,15 +2101,15 @@ scsi_parse_mode_disconnect_reconnect(struct scsi_task *task, int pos, struct scs
+ {
+ 	mp->disconnect_reconnect.buffer_full_ratio = task->datain.data[pos];
+ 	mp->disconnect_reconnect.buffer_empty_ratio = task->datain.data[pos+1];
+-	mp->disconnect_reconnect.bus_inactivity_limit = scsi_get_uint16(&task->datain.data[pos+2]);
+-	mp->disconnect_reconnect.disconnect_time_limit = scsi_get_uint16(&task->datain.data[pos+4]);
+-	mp->disconnect_reconnect.connect_time_limit = scsi_get_uint16(&task->datain.data[pos+6]);
+-	mp->disconnect_reconnect.maximum_burst_size = scsi_get_uint16(&task->datain.data[pos+8]);
++	mp->disconnect_reconnect.bus_inactivity_limit = task_get_uint16(task, pos + 2);
++	mp->disconnect_reconnect.disconnect_time_limit = task_get_uint16(task, pos + 4);
++	mp->disconnect_reconnect.connect_time_limit = task_get_uint16(task, pos + 6);
++	mp->disconnect_reconnect.maximum_burst_size = task_get_uint16(task, pos + 8);
+ 	mp->disconnect_reconnect.emdp = task->datain.data[pos+10] & 0x80;
+ 	mp->disconnect_reconnect.fair_arbitration = (task->datain.data[pos+10]>>4) & 0x0f;
+ 	mp->disconnect_reconnect.dimm = task->datain.data[pos+10] & 0x08;
+ 	mp->disconnect_reconnect.dtdc = task->datain.data[pos+10] & 0x07;
+-	mp->disconnect_reconnect.first_burst_size = scsi_get_uint16(&task->datain.data[pos+12]);
++	mp->disconnect_reconnect.first_burst_size = task_get_uint16(task, pos + 12);
+ }
+ 
+ static void
+@@ -2081,8 +2123,8 @@ scsi_parse_mode_informational_exceptions_control(struct scsi_task *task, int pos
+ 	mp->iec.ebackerr       = task->datain.data[pos] & 0x02;
+ 	mp->iec.logerr         = task->datain.data[pos] & 0x01;
+ 	mp->iec.mrie           = task->datain.data[pos+1] & 0x0f;
+-	mp->iec.interval_timer = scsi_get_uint32(&task->datain.data[pos+2]);
+-	mp->iec.report_count   = scsi_get_uint32(&task->datain.data[pos+6]);
++	mp->iec.interval_timer = task_get_uint32(task, pos + 2);
++	mp->iec.report_count   = task_get_uint32(task, pos + 6);
+ }
+ 
+ 
+@@ -2129,7 +2171,7 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
+ 
+ 		if (mp->spf) {
+ 			mp->subpage_code = task->datain.data[pos++];
+-			mp->len = scsi_get_uint16(&task->datain.data[pos]);
++			mp->len = task_get_uint16(task, pos);
+ 			pos += 2;
+ 		} else {
+ 			mp->subpage_code = 0;
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0005-fix-bug-in-md5-code.patch b/SOURCES/0005-fix-bug-in-md5-code.patch
new file mode 100644
index 0000000..4763911
--- /dev/null
+++ b/SOURCES/0005-fix-bug-in-md5-code.patch
@@ -0,0 +1,27 @@
+From cc742279d0c83523f03a93882fce6bc820851750 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Fri, 3 May 2013 12:43:50 +0200
+Subject: [RHEL7 libiscsi PATCH 05/18] fix bug in md5 code
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit cc742279d0c83523f03a93882fce6bc820851750)
+---
+ lib/md5.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/md5.c b/lib/md5.c
+index daab76c..893956d 100644
+--- a/lib/md5.c
++++ b/lib/md5.c
+@@ -134,7 +134,7 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx)
+ 
+ 	byteSwap(ctx->buf, 4);
+ 	memcpy(digest, ctx->buf, 16);
+-	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
++	memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+ }
+ 
+ #ifndef ASM_MD5
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0006-use-libgcrypt-for-MD5.patch b/SOURCES/0006-use-libgcrypt-for-MD5.patch
new file mode 100644
index 0000000..05325ab
--- /dev/null
+++ b/SOURCES/0006-use-libgcrypt-for-MD5.patch
@@ -0,0 +1,163 @@
+From bcb2950d8ded9ec3a2e3ada8428aeaf725ea2171 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Fri, 3 May 2013 12:47:12 +0200
+Subject: [RHEL7 libiscsi PATCH 06/18] use libgcrypt for MD5
+
+This makes sure that CHAP authentication is disabled if the system
+is running in FIPS 140-2 mode.  MD5 is not a secure algorithm according
+to the standard.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit bcb2950d8ded9ec3a2e3ada8428aeaf725ea2171)
+---
+ Makefile.am  |  6 +++++-
+ configure.ac |  3 +++
+ lib/login.c  | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 60 insertions(+), 9 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 5fea7c8..9a8b2b4 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -34,10 +34,14 @@ dist_noinst_DATA = lib/libiscsi.syms
+ lib_LTLIBRARIES = lib/libiscsi.la
+ lib_libiscsi_la_SOURCES = \
+ 	lib/connect.c lib/crc32c.c lib/discovery.c lib/init.c \
+-	lib/login.c lib/md5.c lib/nop.c lib/pdu.c lib/iscsi-command.c \
++	lib/login.c lib/nop.c lib/pdu.c lib/iscsi-command.c \
+ 	lib/scsi-lowlevel.c lib/socket.c lib/sync.c lib/task_mgmt.c \
+ 	lib/logging.c
+ 
++if !HAVE_LIBGCRYPT
++lib_libiscsi_la_SOURCES += lib/md5.c
++endif
++
+ SONAME=$(firstword $(subst ., ,$(VERSION)))
+ SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION)))
+ lib_libiscsi_la_LDFLAGS = \
+diff --git a/configure.ac b/configure.ac
+index 0b45f91..9d06e3a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -18,6 +18,9 @@ AC_SUBST(WARN_CFLAGS)
+ 
+ AC_CONFIG_HEADER(config.h)
+ 
++AC_CHECK_LIB([gcrypt], [gcry_control])
++AM_CONDITIONAL([HAVE_LIBGCRYPT], [test $ac_cv_lib_gcrypt_gcry_control = yes])
++
+ AC_CACHE_CHECK([for sin_len in sock],libiscsi_cv_HAVE_SOCK_SIN_LEN,[
+ AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/socket.h>
+diff --git a/lib/login.c b/lib/login.c
+index 07ca3dd..29fe4b3 100644
+--- a/lib/login.c
++++ b/lib/login.c
+@@ -35,13 +35,18 @@
+ #include <arpa/inet.h>
+ #endif
+ 
++#include "config.h"
+ #include <stdio.h>
++#include <assert.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "iscsi.h"
+ #include "iscsi-private.h"
+ #include "scsi-lowlevel.h"
+ #include "md5.h"
++#ifdef HAVE_LIBGCRYPT
++#include <gcrypt.h>
++#endif
+ 
+ static int
+ iscsi_login_add_initiatorname(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
+@@ -628,6 +632,41 @@ i2h(int i)
+ 	return i + '0';
+ }
+ 
++#ifndef HAVE_LIBGCRYPT
++typedef struct MD5Context *gcry_md_hd_t;
++#define gcry_md_write MD5Update
++#define GCRY_MD_MD5 1
++
++static inline void gcry_md_open(gcry_md_hd_t *hd, int algo, unsigned int flags)
++{
++	assert(algo == GCRY_MD_MD5 && flags == 0);
++	*hd = malloc(sizeof(struct MD5Context));
++	if (*hd) {
++		MD5Init(*hd);
++	}
++}
++
++static inline void gcry_md_putc(gcry_md_hd_t h, unsigned char c)
++{
++	MD5Update(h, &c, 1);
++}
++
++static inline char *gcry_md_read(gcry_md_hd_t h, int algo)
++{
++	unsigned char digest[16];
++	assert(algo == 0 || algo == GCRY_MD_MD5);
++
++	MD5Final(digest, h);
++	return memcpy(h->buf, digest, sizeof(digest));
++}
++
++static inline void gcry_md_close(gcry_md_hd_t h)
++{
++	memset(h, 0, sizeof(*h));
++	free(h);
++}
++#endif
++
+ static int
+ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
+ {
+@@ -635,7 +674,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
+ 	char * strp;
+ 	unsigned char c, cc[2];
+ 	unsigned char digest[16];
+-	struct MD5Context ctx;
++	gcry_md_hd_t ctx;
+ 	int i;
+ 
+ 	if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG
+@@ -643,22 +682,27 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
+ 		return 0;
+ 	}
+ 
++	gcry_md_open(&ctx, GCRY_MD_MD5, 0);
++	if (!ctx) {
++		iscsi_set_error(iscsi, "Cannot create MD5 algorithm");
++		return -1;
++	}
++
+ 	if (!iscsi->chap_c[0]) {
+ 		iscsi_set_error(iscsi, "No CHAP challenge found");
+ 		return -1;
+ 	}
+-	MD5Init(&ctx);
+-	c = iscsi->chap_i;
+-	MD5Update(&ctx, &c, 1);
+-	MD5Update(&ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));
+-	
++	gcry_md_putc(ctx, iscsi->chap_i);
++	gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));
++
+ 	strp = iscsi->chap_c;
+ 	while (*strp != 0) {
+ 		c = (h2i(strp[0]) << 4) | h2i(strp[1]);
+ 		strp += 2;
+-		MD5Update(&ctx, &c, 1);
++		gcry_md_putc(ctx, c);
+ 	}
+-	MD5Final(digest, &ctx);
++	memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest));
++	gcry_md_close(ctx);
+ 
+ 	strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE);
+ 	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str))
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0007-URL-encoded-Targetnames.patch b/SOURCES/0007-URL-encoded-Targetnames.patch
new file mode 100644
index 0000000..693c4ab
--- /dev/null
+++ b/SOURCES/0007-URL-encoded-Targetnames.patch
@@ -0,0 +1,235 @@
+From e061cba1b91650ab08ae8fa50e8cadb13ac3d97d Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Sun, 16 Jun 2013 11:35:14 -0700
+Subject: [RHEL7 libiscsi PATCH 07/18] URL encoded Targetnames
+
+Assume target names are URL encoded with '%' as the special character.
+
+Any sequence of '%' followed by two bytes in the target name will be replaced
+with the byte that the second two bytes represent in hexadecimal.
+
+Example
+iqn.ronnie.test%3A1234
+will be translated to iqn.ronnie.test:1234
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit e061cba1b91650ab08ae8fa50e8cadb13ac3d97d)
+
+[The right thing to do here is probably to not use this simple-minded code
+ and use QEMU's URI parser.  I need to find a testcase, then I will create
+ a bug. - Paolo]
+---
+ include/iscsi.h |  12 ++++--
+ lib/init.c      | 114 +++++++++++++++++++++++++++++++++++++++-----------------
+ lib/login.c     |   1 +
+ 3 files changed, 88 insertions(+), 39 deletions(-)
+
+diff --git a/include/iscsi.h b/include/iscsi.h
+index f14d404..a4ed932 100644
+--- a/include/iscsi.h
++++ b/include/iscsi.h
+@@ -125,6 +125,10 @@ iscsi_set_initial_r2t(struct iscsi_context *iscsi, enum iscsi_initial_r2t initia
+  * iSCSI URL format :
+  * iscsi://[<username>[%<password>]@]<host>[:<port>]/<target-iqn>/<lun>
+  *
++ * Target names are url encoded with '%' as a special character.
++ * Example:
++ * "iqn.ronnie.test%3A1234" will be translated to "iqn.ronnie.test:1234"
++ *
+  * Function will return a pointer to an iscsi url structure if successful,
+  * or it will return NULL and set iscsi_get_error() accrodingly if there was a problem
+  * with the URL.
+diff --git a/lib/init.c b/lib/init.c
+index 18f3fb2..60a1b6d 100644
+--- a/lib/init.c
++++ b/lib/init.c
+@@ -358,6 +358,45 @@ iscsi_is_logged_in(struct iscsi_context *iscsi)
+ 	return iscsi->is_loggedin;
+ }
+ 
++static int
++h2i(int h)
++{
++	if (h >= 'a' && h <= 'f') {
++		return h - 'a' + 10;
++	}
++	if (h >= 'A' && h <= 'F') {
++		return h - 'A' + 10;
++	}
++	return h - '0';
++}
++
++static void
++iscsi_decode_url_string(char *str)
++{
++	while (*str) {
++		char *tmp = str;
++		char c;
++
++		if (*str++ != '%') {
++			continue;
++		}
++
++		if (*str == 0) {
++			return;
++		}
++		c = h2i(*str++) << 4;
++
++		if (*str == 0) {
++			return;
++		}
++		c |= h2i(*str++);
++
++		*tmp++ = c;
++		memmove(tmp, str, strlen(str));
++		tmp[strlen(str)] = 0;
++	}
++}
++
+ struct iscsi_url *
+ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
+ {
+@@ -373,15 +412,18 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
+ 
+ 	if (strncmp(url, "iscsi://", 8)) {
+ 		if (full) {
+-		iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must be of "
+-				"the form: %s",url,ISCSI_URL_SYNTAX); }
+-		else {
+-		iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal URL must be of "
+-				"the form: %s",url,ISCSI_PORTAL_URL_SYNTAX); }
++			iscsi_set_error(iscsi, "Invalid URL %s\niSCSI URL must "
++				"be of the form: %s",
++				url, ISCSI_URL_SYNTAX);
++		} else {
++			iscsi_set_error(iscsi, "Invalid URL %s\niSCSI Portal "
++				"URL must be of the form: %s",
++				url, ISCSI_PORTAL_URL_SYNTAX);
++		}
+ 		return NULL;
+ 	}
+ 
+-	strncpy(str,url + 8,MAX_STRING_SIZE);
++	strncpy(str,url + 8, MAX_STRING_SIZE);
+ 	portal = str;
+ 
+ 	user   = getenv("LIBISCSI_CHAP_USERNAME");
+@@ -406,56 +448,56 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
+ 	if (full) {
+ 		target = strchr(portal, '/');
+ 		if (target == NULL) {
+-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
+-				"'<target-iqn>'\niSCSI URL must be of the "
+-				"form: %s",
+-				url,
+-				ISCSI_URL_SYNTAX);
++			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
++				"parse '<target-iqn>'\niSCSI URL must be of "
++				"the form: %s",
++				url, ISCSI_URL_SYNTAX);
+ 			return NULL;
+ 		}
+ 		*target++ = 0;
+ 
+ 		if (*target == 0) {
+-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse "
+-				"<target-iqn>\n"
+-				"iSCSI URL must be of the form: %s",
+-				url,
+-				ISCSI_URL_SYNTAX);
++			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
++				"parse <target-iqn>\niSCSI URL must be of the "
++				"form: %s",
++				url, ISCSI_URL_SYNTAX);
+ 			return NULL;
+ 		}
+ 
+ 		lun = strchr(target, '/');
+ 		if (lun == NULL) {
+-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
+-				"iSCSI URL must be of the form: %s",
+-				url,
+-				ISCSI_URL_SYNTAX);
++			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
++				"parse <lun>\niSCSI URL must be of the form: "
++				"%s",
++				url, ISCSI_URL_SYNTAX);
+ 			return NULL;
+ 		}
+ 		*lun++ = 0;
+ 
+ 		l = strtol(lun, &tmp, 10);
+ 		if (*lun == 0 || *tmp != 0) {
+-			iscsi_set_error(iscsi, "Invalid URL %s\nCould not parse <lun>\n"
+-				"iSCSI URL must be of the form: %s",
+-				url,
+-				ISCSI_URL_SYNTAX);
++			iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
++				"parse <lun>\niSCSI URL must be of the form: "
++				"%s",
++				url, ISCSI_URL_SYNTAX);
+ 			return NULL;
+ 		}
+-	}
+-	else
+-	{
++	} else {
+ 		tmp=strchr(portal,'/');
+-		if (tmp) *tmp=0;
++		if (tmp) {
++			*tmp=0;
++		}
+ 	}
+ 	
+-	if (iscsi != NULL)
++	if (iscsi != NULL) {
+ 		iscsi_url = iscsi_malloc(iscsi, sizeof(struct iscsi_url));
+-	else
++	} else {
+ 		iscsi_url = malloc(sizeof(struct iscsi_url));
+-	
++	}
++
+ 	if (iscsi_url == NULL) {
+-		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate iscsi_url structure");
++		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
++			"iscsi_url structure");
+ 		return NULL;
+ 	}
+ 	memset(iscsi_url, 0, sizeof(struct iscsi_url));
+@@ -464,15 +506,17 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
+ 	strncpy(iscsi_url->portal,portal,MAX_STRING_SIZE);
+ 
+ 	if (user != NULL && passwd != NULL) {
+-		strncpy(iscsi_url->user,user,MAX_STRING_SIZE);
+-		strncpy(iscsi_url->passwd,passwd,MAX_STRING_SIZE);
++		strncpy(iscsi_url->user, user, MAX_STRING_SIZE);
++		strncpy(iscsi_url->passwd, passwd, MAX_STRING_SIZE);
+ 	}
+ 
+ 	if (full) {
+-		strncpy(iscsi_url->target,target,MAX_STRING_SIZE);
++		strncpy(iscsi_url->target, target, MAX_STRING_SIZE);
+ 		iscsi_url->lun = l;
+ 	}
+ 
++	iscsi_decode_url_string(&iscsi_url->target[0]);
++
+ 	return iscsi_url;
+ }
+ 
+diff --git a/lib/login.c b/lib/login.c
+index 29fe4b3..0448ce2 100644
+--- a/lib/login.c
++++ b/lib/login.c
+@@ -622,6 +622,7 @@ h2i(int h)
+ 	}
+ 	return h - '0';
+ }
++
+ static int
+ i2h(int i)
+ {
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch b/SOURCES/0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch
new file mode 100644
index 0000000..c310788
--- /dev/null
+++ b/SOURCES/0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch
@@ -0,0 +1,539 @@
+From 704e0f6448f4a9ce0c4c9a030679ab97a37850e8 Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Sun, 12 May 2013 13:57:15 -0700
+Subject: [RHEL7 libiscsi PATCH 08/18] SCSI: add a safe function to read a byte from the datain
+ buffer and use it throughout the unmarshalling code
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 704e0f6448f4a9ce0c4c9a030679ab97a37850e8)
+---
+ lib/scsi-lowlevel.c | 302 ++++++++++++++++++++++++++++------------------------
+ 1 file changed, 163 insertions(+), 139 deletions(-)
+
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index 85f7b1d..1f51f32 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -274,6 +274,16 @@ task_get_uint16(struct scsi_task *task, int offset)
+ 	}
+ }
+ 
++static inline uint8_t
++task_get_uint8(struct scsi_task *task, int offset)
++{
++	if (offset <= task->datain.size - 1) {
++		return task->datain.data[offset];
++	} else {
++		return 0;
++	}
++}
++
+ inline void
+ scsi_set_uint64(unsigned char *c, uint64_t v)
+ {
+@@ -501,49 +511,49 @@ scsi_readtoc_desc_unmarshall(struct scsi_task *task, struct scsi_readtoc_list *l
+ 	switch(scsi_readtoc_format(task)) {
+ 	case SCSI_READ_TOC:
+ 		list->desc[i].desc.toc.adr
+-			= task->datain.data[4+8*i+1] & 0xf0;
++			= task_get_uint8(task, 4 + 8 * i + 1) & 0xf0;
+ 		list->desc[i].desc.toc.control
+-			= task->datain.data[4+8*i+1] & 0x0f;
++			= task_get_uint8(task, 4 + 8 * i + 1) & 0x0f;
+ 		list->desc[i].desc.toc.track
+-			= task->datain.data[4+8*i+2];
++			= task_get_uint8(task, 4 + 8 * i + 2);
+ 		list->desc[i].desc.toc.lba
+ 			= task_get_uint32(task, 4 + 8 * i + 4);
+ 		break;
+ 	case SCSI_READ_SESSION_INFO:
+ 		list->desc[i].desc.ses.adr
+-			= task->datain.data[4+8*i+1] & 0xf0;
++			= task_get_uint8(task, 4 + 8 * i + 1) & 0xf0;
+ 		list->desc[i].desc.ses.control
+-			= task->datain.data[4+8*i+1] & 0x0f;
++			= task_get_uint8(task, 4 + 8 * i + 1) & 0x0f;
+ 		list->desc[i].desc.ses.first_in_last
+-			= task->datain.data[4+8*i+2];
++			= task_get_uint8(task, 4 + 8 * i + 2);
+ 		list->desc[i].desc.ses.lba
+ 			= task_get_uint32(task, 4 + 8 * i + 4);
+ 		break;
+ 	case SCSI_READ_FULL_TOC:
+ 		list->desc[i].desc.full.session
+-			= task->datain.data[4+11*i+0] & 0xf0;
++			= task_get_uint8(task, 4 + 11 * i + 0) & 0xf0;
+ 		list->desc[i].desc.full.adr
+-			= task->datain.data[4+11*i+1] & 0xf0;
++			= task_get_uint8(task, 4 + 11 * i + 1) & 0xf0;
+ 		list->desc[i].desc.full.control
+-			= task->datain.data[4+11*i+1] & 0x0f;
++			= task_get_uint8(task, 4 + 11 * i + 1) & 0x0f;
+ 		list->desc[i].desc.full.tno
+-			= task->datain.data[4+11*i+2];
++			= task_get_uint8(task, 4 + 11 * i + 2);
+ 		list->desc[i].desc.full.point
+-			= task->datain.data[4+11*i+3];
++			= task_get_uint8(task, 4 + 11 * i + 3);
+ 		list->desc[i].desc.full.min
+-			= task->datain.data[4+11*i+4];
++			= task_get_uint8(task, 4 + 11 * i + 4);
+ 		list->desc[i].desc.full.sec
+-			= task->datain.data[4+11*i+5];
++			= task_get_uint8(task, 4 + 11 * i + 5);
+ 		list->desc[i].desc.full.frame
+-			= task->datain.data[4+11*i+6];
++			= task_get_uint8(task, 4 + 11 * i + 6);
+ 		list->desc[i].desc.full.zero
+-			= task->datain.data[4+11*i+7];
++			= task_get_uint8(task, 4 + 11 * i + 7);
+ 		list->desc[i].desc.full.pmin
+-			= task->datain.data[4+11*i+8];
++			= task_get_uint8(task, 4 + 11 * i + 8);
+ 		list->desc[i].desc.full.psec
+-			= task->datain.data[4+11*i+9];
++			= task_get_uint8(task, 4 + 11 * i + 9);
+ 		list->desc[i].desc.full.pframe
+-			= task->datain.data[4+11*i+10];
++			= task_get_uint8(task, 4 + 11 * i + 10);
+ 		break;
+ 	default:
+ 		break;
+@@ -580,8 +590,8 @@ scsi_readtoc_datain_unmarshall(struct scsi_task *task)
+ 	}
+ 
+ 	list->num = num_desc;
+-	list->first = task->datain.data[2];
+-	list->last = task->datain.data[3];
++	list->first = task_get_uint8(task, 2);
++	list->last = task_get_uint8(task, 3);
+ 
+ 	for (i = 0; i < num_desc; i++) {
+ 		scsi_readtoc_desc_unmarshall(task, list, i);
+@@ -655,12 +665,12 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
+ 		rc16->returned_lba = task_get_uint32(task, 0);
+ 		rc16->returned_lba = (rc16->returned_lba << 32) | task_get_uint32(task, 4);
+ 		rc16->block_length = task_get_uint32(task, 8);
+-		rc16->p_type       = (task->datain.data[12] >> 1) & 0x07;
+-		rc16->prot_en      = task->datain.data[12] & 0x01;
+-		rc16->p_i_exp      = (task->datain.data[13] >> 4) & 0x0f;
+-		rc16->lbppbe       = task->datain.data[13] & 0x0f;
+-		rc16->lbpme        = !!(task->datain.data[14] & 0x80);
+-		rc16->lbprz        = !!(task->datain.data[14] & 0x40);
++		rc16->p_type       = (task_get_uint8(task, 12) >> 1) & 0x07;
++		rc16->prot_en      = task_get_uint8(task, 12) & 0x01;
++		rc16->p_i_exp      = (task_get_uint8(task, 13) >> 4) & 0x0f;
++		rc16->lbppbe       = task_get_uint8(task, 13) & 0x0f;
++		rc16->lbpme        = !!(task_get_uint8(task, 14) & 0x80);
++		rc16->lbprz        = !!(task_get_uint8(task, 14) & 0x40);
+ 		rc16->lalba        = task_get_uint16(task, 14) & 0x3fff;
+ 		return rc16;
+ 	}
+@@ -694,7 +704,7 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
+ 
+ 			gls->descriptors[i].num_blocks = task_get_uint32(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 8);
+ 
+-			gls->descriptors[i].provisioning = task->datain.data[8 + i * sizeof(struct scsi_lba_status_descriptor) + 12] & 0x0f;
++			gls->descriptors[i].provisioning = task_get_uint8(task, 8 + i * sizeof(struct scsi_lba_status_descriptor) + 12) & 0x0f;
+ 		}
+ 
+ 		return gls;
+@@ -771,7 +781,7 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 			rr->reserved = 1;
+ 			rr->reservation_key =
+ 				task_get_uint64(task, 8);
+-			rr->pr_type = task->datain.data[21] & 0xff;
++			rr->pr_type = task_get_uint8(task, 21) & 0xff;
+ 		}
+ 
+ 		return rr;
+@@ -782,12 +792,12 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 			return NULL;
+ 		}
+ 		rc->length         = task_get_uint16(task, 0);
+-		rc->crh            = !!(task->datain.data[2] & 0x10);
+-		rc->sip_c          = !!(task->datain.data[2] & 0x08);
+-		rc->atp_c          = !!(task->datain.data[2] & 0x04);
+-		rc->ptpl_c         = !!(task->datain.data[2] & 0x01);
+-		rc->tmv            = !!(task->datain.data[3] & 0x80);
+-		rc->allow_commands = task->datain.data[3] >> 4;
++		rc->crh            = !!(task_get_uint8(task, 2) & 0x10);
++		rc->sip_c          = !!(task_get_uint8(task, 2) & 0x08);
++		rc->atp_c          = !!(task_get_uint8(task, 2) & 0x04);
++		rc->ptpl_c         = !!(task_get_uint8(task, 2) & 0x01);
++		rc->tmv            = !!(task_get_uint8(task, 3) & 0x80);
++		rc->allow_commands = task_get_uint8(task, 3) >> 4;
+ 		rc->persistent_reservation_type_mask = task_get_uint16(task, 4);
+ 
+ 		return rc;
+@@ -1003,14 +1013,14 @@ static int
+ scsi_inquiry_datain_getfullsize(struct scsi_task *task)
+ {
+ 	if (scsi_inquiry_evpd_set(task) == 0) {
+-		return task->datain.data[4] + 5;
++		return task_get_uint8(task, 4) + 5;
+ 	}
+ 
+ 	switch (scsi_inquiry_page_code(task)) {
+ 	case SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES:
+ 	case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
+ 	case SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER:
+-		return task->datain.data[3] + 4;
++		return task_get_uint8(task, 3) + 4;
+ 	case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
+ 	case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
+ 	case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
+@@ -1030,28 +1040,28 @@ scsi_inquiry_unmarshall_standard(struct scsi_task *task)
+ 		return NULL;
+ 	}
+ 
+-	inq->qualifier              = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type            = task->datain.data[0]&0x1f;
+-	inq->rmb                    = !!(task->datain.data[1]&0x80);
+-	inq->version                = task->datain.data[2];
+-	inq->normaca                = !!(task->datain.data[3]&0x20);
+-	inq->hisup                  = !!(task->datain.data[3]&0x10);
+-	inq->response_data_format   = task->datain.data[3]&0x0f;
++	inq->qualifier              = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type            = task_get_uint8(task, 0) & 0x1f;
++	inq->rmb                    = !!(task_get_uint8(task, 1) & 0x80);
++	inq->version                = task_get_uint8(task, 2);
++	inq->normaca                = !!(task_get_uint8(task, 3) & 0x20);
++	inq->hisup                  = !!(task_get_uint8(task, 3) & 0x10);
++	inq->response_data_format   = task_get_uint8(task, 3) & 0x0f;
+ 
+-	inq->additional_length      = task->datain.data[4];
++	inq->additional_length      = task_get_uint8(task, 4);
+ 
+-	inq->sccs                   = !!(task->datain.data[5]&0x80);
+-	inq->acc                    = !!(task->datain.data[5]&0x40);
+-	inq->tpgs                   = (task->datain.data[5]>>4)&0x03;
+-	inq->threepc                = !!(task->datain.data[5]&0x08);
+-	inq->protect                = !!(task->datain.data[5]&0x01);
++	inq->sccs                   = !!(task_get_uint8(task, 5) & 0x80);
++	inq->acc                    = !!(task_get_uint8(task, 5) & 0x40);
++	inq->tpgs                   = (task_get_uint8(task, 5) >> 4) & 0x03;
++	inq->threepc                = !!(task_get_uint8(task, 5) & 0x08);
++	inq->protect                = !!(task_get_uint8(task, 5) & 0x01);
+ 
+-	inq->encserv                = !!(task->datain.data[6]&0x40);
+-	inq->multip                 = !!(task->datain.data[6]&0x10);
+-	inq->addr16                 = !!(task->datain.data[6]&0x01);
+-	inq->wbus16                 = !!(task->datain.data[7]&0x20);
+-	inq->sync                   = !!(task->datain.data[7]&0x10);
+-	inq->cmdque                 = !!(task->datain.data[7]&0x02);
++	inq->encserv                = !!(task_get_uint8(task, 6) & 0x40);
++	inq->multip                 = !!(task_get_uint8(task, 6) & 0x10);
++	inq->addr16                 = !!(task_get_uint8(task, 6) & 0x01);
++	inq->wbus16                 = !!(task_get_uint8(task, 7) & 0x20);
++	inq->sync                   = !!(task_get_uint8(task, 7) & 0x10);
++	inq->cmdque                 = !!(task_get_uint8(task, 7) & 0x02);
+ 
+ 	memcpy(&inq->vendor_identification[0],
+ 	       &task->datain.data[8], 8);
+@@ -1060,9 +1070,9 @@ scsi_inquiry_unmarshall_standard(struct scsi_task *task)
+ 	memcpy(&inq->product_revision_level[0],
+ 	       &task->datain.data[32], 4);
+ 
+-	inq->clocking               = (task->datain.data[56]>>2)&0x03;
+-	inq->qas                    = !!(task->datain.data[56]&0x02);
+-	inq->ius                    = !!(task->datain.data[56]&0x01);
++	inq->clocking               = (task_get_uint8(task, 56) >> 2) & 0x03;
++	inq->qas                    = !!(task_get_uint8(task, 56) & 0x02);
++	inq->ius                    = !!(task_get_uint8(task, 56) & 0x01);
+ 
+ 	return inq;
+ }
+@@ -1079,11 +1089,11 @@ scsi_inquiry_unmarshall_supported_pages(struct scsi_task *task)
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type = task->datain.data[0]&0x1f;
+-	inq->pagecode = task->datain.data[1];
++	inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode = task_get_uint8(task, 1);
+ 
+-	inq->num_pages = task->datain.data[3];
++	inq->num_pages = task_get_uint8(task, 3);
+ 	inq->pages = scsi_malloc(task, inq->num_pages);
+ 	if (inq->pages == NULL) {
+ 		free (inq);
+@@ -1101,17 +1111,17 @@ scsi_inquiry_unmarshall_unit_serial_number(struct scsi_task* task)
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type = task->datain.data[0]&0x1f;
+-	inq->pagecode = task->datain.data[1];
++	inq->qualifier = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode = task_get_uint8(task, 1);
+ 
+-	inq->usn = scsi_malloc(task, task->datain.data[3]+1);
++	inq->usn = scsi_malloc(task, task_get_uint8(task, 3) + 1);
+ 	if (inq->usn == NULL) {
+ 		free(inq);
+ 		return NULL;
+ 	}
+-	memcpy(inq->usn, &task->datain.data[4], task->datain.data[3]);
+-	inq->usn[task->datain.data[3]] = 0;
++	memcpy(inq->usn, &task->datain.data[4], task_get_uint8(task, 3));
++	inq->usn[task_get_uint8(task, 3)] = 0;
+ 	return inq;
+ }
+ 
+@@ -1119,16 +1129,16 @@ static struct scsi_inquiry_device_identification *
+ scsi_inquiry_unmarshall_device_identification(struct scsi_task *task)
+ {
+ 	struct scsi_inquiry_device_identification *inq = scsi_malloc(task,
+-								     sizeof(*inq));
++							     sizeof(*inq));
+ 	int remaining = task_get_uint16(task, 2);
+ 	unsigned char *dptr;
+ 
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier             = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type           = task->datain.data[0]&0x1f;
+-	inq->pagecode              = task->datain.data[1];
++	inq->qualifier             = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type           = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode              = task_get_uint8(task, 1);
+ 
+ 	dptr = &task->datain.data[4];
+ 	while (remaining > 0) {
+@@ -1183,12 +1193,12 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier             = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type           = task->datain.data[0]&0x1f;
+-	inq->pagecode              = task->datain.data[1];
++	inq->qualifier             = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type           = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode              = task_get_uint8(task, 1);
+ 
+-	inq->wsnz                  = task->datain.data[4] & 0x01;
+-	inq->max_cmp               = task->datain.data[5];
++	inq->wsnz                  = task_get_uint8(task, 4) & 0x01;
++	inq->max_cmp               = task_get_uint8(task, 5);
+ 	inq->opt_gran              = task_get_uint16(task, 6);
+ 	inq->max_xfer_len          = task_get_uint32(task, 8);
+ 	inq->opt_xfer_len          = task_get_uint32(task, 12);
+@@ -1196,7 +1206,7 @@ scsi_inquiry_unmarshall_block_limits(struct scsi_task *task)
+ 	inq->max_unmap             = task_get_uint32(task, 20);
+ 	inq->max_unmap_bdc         = task_get_uint32(task, 24);
+ 	inq->opt_unmap_gran        = task_get_uint32(task, 28);
+-	inq->ugavalid              = !!(task->datain.data[32]&0x80);
++	inq->ugavalid              = !!(task_get_uint8(task, 32)&0x80);
+ 	inq->unmap_gran_align      = task_get_uint32(task, 32) & 0x7fffffff;
+ 	inq->max_ws_len            = task_get_uint32(task, 36);
+ 	inq->max_ws_len            = (inq->max_ws_len << 32)
+@@ -1213,9 +1223,9 @@ scsi_inquiry_unmarshall_block_device_characteristics(struct scsi_task *task)
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier             = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type           = task->datain.data[0]&0x1f;
+-	inq->pagecode              = task->datain.data[1];
++	inq->qualifier             = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type           = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode              = task_get_uint8(task, 1);
+ 
+ 	inq->medium_rotation_rate  = task_get_uint16(task, 4);
+ 	return inq;
+@@ -1229,18 +1239,18 @@ scsi_inquiry_unmarshall_logical_block_provisioning(struct scsi_task *task)
+ 	if (inq == NULL) {
+ 		return NULL;
+ 	}
+-	inq->qualifier             = (task->datain.data[0]>>5)&0x07;
+-	inq->device_type           = task->datain.data[0]&0x1f;
+-	inq->pagecode              = task->datain.data[1];
++	inq->qualifier             = (task_get_uint8(task, 0) >> 5) & 0x07;
++	inq->device_type           = task_get_uint8(task, 0) & 0x1f;
++	inq->pagecode              = task_get_uint8(task, 1);
+ 
+-	inq->threshold_exponent = task->datain.data[4];
+-	inq->lbpu               = !!(task->datain.data[5] & 0x80);
+-	inq->lbpws              = !!(task->datain.data[5] & 0x40);
+-	inq->lbpws10            = !!(task->datain.data[5] & 0x20);
+-	inq->lbprz              = !!(task->datain.data[5] & 0x04);
+-	inq->anc_sup            = !!(task->datain.data[5] & 0x02);
+-	inq->dp	                = !!(task->datain.data[5] & 0x01);
+-	inq->provisioning_type  = task->datain.data[6] & 0x07;
++	inq->threshold_exponent = task_get_uint8(task, 4);
++	inq->lbpu               = !!(task_get_uint8(task, 5) & 0x80);
++	inq->lbpws              = !!(task_get_uint8(task, 5) & 0x40);
++	inq->lbpws10            = !!(task_get_uint8(task, 5) & 0x20);
++	inq->lbprz              = !!(task_get_uint8(task, 5) & 0x04);
++	inq->anc_sup            = !!(task_get_uint8(task, 5) & 0x02);
++	inq->dp	                = !!(task_get_uint8(task, 5) & 0x01);
++	inq->provisioning_type  = task_get_uint8(task, 6) & 0x07;
+ 
+ 	return inq;
+ }
+@@ -2062,7 +2072,7 @@ scsi_modesense6_datain_getfullsize(struct scsi_task *task)
+ {
+ 	int len;
+ 
+-	len = task->datain.data[0] + 1;
++	len = task_get_uint8(task, 0) + 1;
+ 
+ 	return len;
+ }
+@@ -2070,59 +2080,73 @@ scsi_modesense6_datain_getfullsize(struct scsi_task *task)
+ static void
+ scsi_parse_mode_caching(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
+ {
+-	mp->caching.ic   = task->datain.data[pos] & 0x80;
+-	mp->caching.abpf = task->datain.data[pos] & 0x40;
+-	mp->caching.cap  = task->datain.data[pos] & 0x20;
+-	mp->caching.disc = task->datain.data[pos] & 0x10;
+-	mp->caching.size = task->datain.data[pos] & 0x08;
+-	mp->caching.wce  = task->datain.data[pos] & 0x04;
+-	mp->caching.mf   = task->datain.data[pos] & 0x02;
+-	mp->caching.rcd  = task->datain.data[pos] & 0x01;
+-
+-	mp->caching.demand_read_retention_priority = (task->datain.data[pos+1] >> 4) & 0x0f;
+-	mp->caching.write_retention_priority       = task->datain.data[pos+1] & 0x0f;
+-
+-	mp->caching.disable_prefetch_transfer_length = task_get_uint16(task, pos + 2);
++	mp->caching.ic   = task_get_uint8(task, pos) & 0x80;
++	mp->caching.abpf = task_get_uint8(task, pos) & 0x40;
++	mp->caching.cap  = task_get_uint8(task, pos) & 0x20;
++	mp->caching.disc = task_get_uint8(task, pos) & 0x10;
++	mp->caching.size = task_get_uint8(task, pos) & 0x08;
++	mp->caching.wce  = task_get_uint8(task, pos) & 0x04;
++	mp->caching.mf   = task_get_uint8(task, pos) & 0x02;
++	mp->caching.rcd  = task_get_uint8(task, pos) & 0x01;
++
++	mp->caching.demand_read_retention_priority =
++		(task_get_uint8(task, pos + 1) >> 4) & 0x0f;
++	mp->caching.write_retention_priority       =
++		task_get_uint8(task, pos + 1) & 0x0f;
++
++	mp->caching.disable_prefetch_transfer_length =
++		task_get_uint16(task, pos + 2);
+ 	mp->caching.minimum_prefetch = task_get_uint16(task, pos + 4);
+ 	mp->caching.maximum_prefetch = task_get_uint16(task, pos + 6);
+ 	mp->caching.maximum_prefetch_ceiling = task_get_uint16(task, pos + 8);
+ 
+-	mp->caching.fsw    = task->datain.data[pos+10] & 0x80;
+-	mp->caching.lbcss  = task->datain.data[pos+10] & 0x40;
+-	mp->caching.dra    = task->datain.data[pos+10] & 0x20;
+-	mp->caching.nv_dis = task->datain.data[pos+10] & 0x01;
++	mp->caching.fsw    = task_get_uint8(task, pos + 10) & 0x80;
++	mp->caching.lbcss  = task_get_uint8(task, pos + 10) & 0x40;
++	mp->caching.dra    = task_get_uint8(task, pos + 10) & 0x20;
++	mp->caching.nv_dis = task_get_uint8(task, pos + 10) & 0x01;
+ 
+-	mp->caching.number_of_cache_segments = task->datain.data[pos+11];
++	mp->caching.number_of_cache_segments = task_get_uint8(task, pos + 11);
+ 	mp->caching.cache_segment_size = task_get_uint16(task, pos + 12);
+ }
+ 
+ static void
+ scsi_parse_mode_disconnect_reconnect(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
+ {
+-	mp->disconnect_reconnect.buffer_full_ratio = task->datain.data[pos];
+-	mp->disconnect_reconnect.buffer_empty_ratio = task->datain.data[pos+1];
+-	mp->disconnect_reconnect.bus_inactivity_limit = task_get_uint16(task, pos + 2);
+-	mp->disconnect_reconnect.disconnect_time_limit = task_get_uint16(task, pos + 4);
+-	mp->disconnect_reconnect.connect_time_limit = task_get_uint16(task, pos + 6);
+-	mp->disconnect_reconnect.maximum_burst_size = task_get_uint16(task, pos + 8);
+-	mp->disconnect_reconnect.emdp = task->datain.data[pos+10] & 0x80;
+-	mp->disconnect_reconnect.fair_arbitration = (task->datain.data[pos+10]>>4) & 0x0f;
+-	mp->disconnect_reconnect.dimm = task->datain.data[pos+10] & 0x08;
+-	mp->disconnect_reconnect.dtdc = task->datain.data[pos+10] & 0x07;
+-	mp->disconnect_reconnect.first_burst_size = task_get_uint16(task, pos + 12);
++	mp->disconnect_reconnect.buffer_full_ratio =
++		task_get_uint8(task, pos);
++	mp->disconnect_reconnect.buffer_empty_ratio =
++		task_get_uint8(task, pos + 1);
++	mp->disconnect_reconnect.bus_inactivity_limit =
++		task_get_uint16(task, pos + 2);
++	mp->disconnect_reconnect.disconnect_time_limit =
++		task_get_uint16(task, pos + 4);
++	mp->disconnect_reconnect.connect_time_limit =
++		task_get_uint16(task, pos + 6);
++	mp->disconnect_reconnect.maximum_burst_size =
++		task_get_uint16(task, pos + 8);
++	mp->disconnect_reconnect.emdp =
++		task_get_uint8(task, pos + 10) & 0x80;
++	mp->disconnect_reconnect.fair_arbitration =
++		(task_get_uint8(task, pos + 10) >> 4) & 0x0f;
++	mp->disconnect_reconnect.dimm =
++		task_get_uint8(task, pos + 10) & 0x08;
++	mp->disconnect_reconnect.dtdc =
++		task_get_uint8(task, pos + 10) & 0x07;
++	mp->disconnect_reconnect.first_burst_size =
++		task_get_uint16(task, pos + 12);
+ }
+ 
+ static void
+ scsi_parse_mode_informational_exceptions_control(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
+ {
+-	mp->iec.perf           = task->datain.data[pos] & 0x80;
+-	mp->iec.ebf            = task->datain.data[pos] & 0x20;
+-	mp->iec.ewasc          = task->datain.data[pos] & 0x10;
+-	mp->iec.dexcpt         = task->datain.data[pos] & 0x08;
+-	mp->iec.test           = task->datain.data[pos] & 0x04;
+-	mp->iec.ebackerr       = task->datain.data[pos] & 0x02;
+-	mp->iec.logerr         = task->datain.data[pos] & 0x01;
+-	mp->iec.mrie           = task->datain.data[pos+1] & 0x0f;
++	mp->iec.perf           = task_get_uint8(task, pos) & 0x80;
++	mp->iec.ebf            = task_get_uint8(task, pos) & 0x20;
++	mp->iec.ewasc          = task_get_uint8(task, pos) & 0x10;
++	mp->iec.dexcpt         = task_get_uint8(task, pos) & 0x08;
++	mp->iec.test           = task_get_uint8(task, pos) & 0x04;
++	mp->iec.ebackerr       = task_get_uint8(task, pos) & 0x02;
++	mp->iec.logerr         = task_get_uint8(task, pos) & 0x01;
++	mp->iec.mrie           = task_get_uint8(task, pos + 1) & 0x0f;
+ 	mp->iec.interval_timer = task_get_uint32(task, pos + 2);
+ 	mp->iec.report_count   = task_get_uint32(task, pos + 6);
+ }
+@@ -2146,10 +2170,10 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
+ 		return NULL;
+ 	}
+ 
+-	ms->mode_data_length          = task->datain.data[0];
+-	ms->medium_type               = task->datain.data[1];
+-	ms->device_specific_parameter = task->datain.data[2];
+-	ms->block_descriptor_length   = task->datain.data[3];
++	ms->mode_data_length          = task_get_uint8(task, 0);
++	ms->medium_type               = task_get_uint8(task, 1);
++	ms->device_specific_parameter = task_get_uint8(task, 2);
++	ms->block_descriptor_length   = task_get_uint8(task, 3);
+ 	ms->pages                     = NULL;
+ 
+ 	if (ms->mode_data_length + 1 > task->datain.size) {
+@@ -2164,18 +2188,18 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task)
+ 		if (mp == NULL) {
+ 			return ms;
+ 		}
+-		mp->ps           = task->datain.data[pos] & 0x80;
+-		mp->spf          = task->datain.data[pos] & 0x40;
+-		mp->page_code    = task->datain.data[pos] & 0x3f;
++		mp->ps           = task_get_uint8(task, pos) & 0x80;
++		mp->spf          = task_get_uint8(task, pos) & 0x40;
++		mp->page_code    = task_get_uint8(task, pos) & 0x3f;
+ 		pos++;
+ 
+ 		if (mp->spf) {
+-			mp->subpage_code = task->datain.data[pos++];
++			mp->subpage_code = task_get_uint8(task, pos++);
+ 			mp->len = task_get_uint16(task, pos);
+ 			pos += 2;
+ 		} else {
+ 			mp->subpage_code = 0;
+-			mp->len          = task->datain.data[pos++];
++			mp->len          = task_get_uint8(task, pos++);
+ 		}
+ 
+ 		switch (mp->page_code) {
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch b/SOURCES/0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch
new file mode 100644
index 0000000..48e1726
--- /dev/null
+++ b/SOURCES/0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch
@@ -0,0 +1,114 @@
+From 0a7c084603663a1e63b01bd677429a20bc7d4c62 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Mon, 1 Jul 2013 15:57:44 +0200
+Subject: [RHEL7 libiscsi PATCH 09/18] scsi-lowlevel: do not use unsafe pointer casts
+
+Casting unsigned char * pointers to uint32_t * may cause wrong
+results if the pointers are not correctly aligned.  Instead,
+build up the big-endian values from each byte with multiple
+dereferences of the original pointer.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 0a7c084603663a1e63b01bd677429a20bc7d4c62)
+---
+ lib/scsi-lowlevel.c | 36 +++++++++++++++++++++---------------
+ 1 file changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index ad94eef..37f41d5 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -212,10 +212,10 @@ scsi_get_uint64(const unsigned char *c)
+ {
+ 	uint64_t val;
+ 
+-	val = ntohl(*(uint32_t *)c);
++	val = scsi_get_uint32(c);
+ 	val <<= 32;
+ 	c += 4;
+-	val |= ntohl(*(uint32_t *)c);
++	val |= scsi_get_uint32(c);
+ 
+ 	return val;
+ }
+@@ -223,13 +223,21 @@ scsi_get_uint64(const unsigned char *c)
+ inline uint32_t
+ scsi_get_uint32(const unsigned char *c)
+ {
+-	return ntohl(*(uint32_t *)c);
++	uint32_t val;
++	val = c[0];
++	val = (val << 8) | c[1];
++	val = (val << 8) | c[2];
++	val = (val << 8) | c[3];
++	return val;
+ }
+ 
+ inline uint16_t
+ scsi_get_uint16(const unsigned char *c)
+ {
+-	return ntohs(*(uint16_t *)c);
++	uint16_t val;
++	val = c[0];
++	val = (val << 8) | c[1];
++	return val;
+ }
+ 
+ static inline uint64_t
+@@ -237,14 +245,8 @@ task_get_uint64(struct scsi_task *task, int offset)
+ {
+ 	if (offset <= task->datain.size - 8) {
+ 		const unsigned char *c = &task->datain.data[offset];
+-		uint64_t val;
+ 
+-		val = ntohl(*(uint32_t *)c);
+-		val <<= 32;
+-		c += 4;
+-		val |= ntohl(*(uint32_t *)c);
+-
+-		return val;
++		return scsi_get_uint64(c);
+ 	} else {
+ 		return 0;
+ 	}
+@@ -256,7 +258,7 @@ task_get_uint32(struct scsi_task *task, int offset)
+ 	if (offset <= task->datain.size - 4) {
+ 		const unsigned char *c = &task->datain.data[offset];
+ 
+-		return ntohl(*(uint32_t *)c);
++		return scsi_get_uint32(c);
+ 	} else {
+ 		return 0;
+ 	}
+@@ -268,7 +270,7 @@ task_get_uint16(struct scsi_task *task, int offset)
+ 	if (offset <= task->datain.size - 2) {
+ 		const unsigned char *c = &task->datain.data[offset];
+ 
+-		return ntohs(*(uint16_t *)c);
++		return scsi_get_uint16(c);
+ 	} else {
+ 		return 0;
+ 	}
+@@ -300,13 +302,17 @@ scsi_set_uint64(unsigned char *c, uint64_t v)
+ inline void
+ scsi_set_uint32(unsigned char *c, uint32_t val)
+ {
+-	*(uint32_t *)c = htonl(val);
++	c[0] = val >> 24;
++	c[1] = val >> 16;
++	c[2] = val >> 8;
++	c[3] = val;
+ }
+ 
+ inline void
+ scsi_set_uint16(unsigned char *c, uint16_t val)
+ {
+-	*(uint16_t *)c = htons(val);
++	c[0] = val >> 8;
++	c[1] = val;
+ }
+ 
+ /*
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0010-Add-a-cast-to-ssize_t.patch b/SOURCES/0010-Add-a-cast-to-ssize_t.patch
new file mode 100644
index 0000000..70d9ff8
--- /dev/null
+++ b/SOURCES/0010-Add-a-cast-to-ssize_t.patch
@@ -0,0 +1,27 @@
+From b555bbebdd1c92b025a44955a988cc2eed646c2b Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Sat, 29 Jun 2013 11:12:41 -0700
+Subject: [RHEL7 libiscsi PATCH 10/18] Add a cast to ssize_t
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit b555bbebdd1c92b025a44955a988cc2eed646c2b)
+---
+ lib/socket.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/socket.c b/lib/socket.c
+index a855f92..6fc3b41 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -517,7 +517,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
+ 	}
+ 
+ 	data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
+-	if (data_size < 0 || data_size > iscsi->initiator_max_recv_data_segment_length) {
++	if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) {
+ 		iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
+ 		return -1;
+ 	}
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0011-do-not-build-test-tool.patch b/SOURCES/0011-do-not-build-test-tool.patch
new file mode 100644
index 0000000..11dfd39
--- /dev/null
+++ b/SOURCES/0011-do-not-build-test-tool.patch
@@ -0,0 +1,26 @@
+From b036ca4d5b414f269a0c00da2624129858e5bf3e Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Fri, 30 Aug 2013 15:55:13 +0200
+Subject: [RHEL7 libiscsi PATCH 11/18] do not build test tool
+
+The test tool is not needed in RHEL.  Do not build it nor
+install it.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+
+diff --git a/Makefile.am b/Makefile.am
+index 114dd09..d5acf30 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -59,7 +59,7 @@ bin_iscsi_dd_SOURCES = examples/iscsi-dd.c
+ 
+ # libiscsi test tool
+ 
+-noinst_PROGRAMS += bin/iscsi-test
++EXTRA_PROGRAMS += bin/iscsi-test
+ dist_noinst_HEADERS += test-tool/iscsi-support.h \
+ 		       test-tool/iscsi-test.h \
+ 		       test-tool/iscsi-test-cu.h
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0012-bump-soname.patch b/SOURCES/0012-bump-soname.patch
new file mode 100644
index 0000000..3e2cdaa
--- /dev/null
+++ b/SOURCES/0012-bump-soname.patch
@@ -0,0 +1,25 @@
+From d4a6e4b3e3c6becf507158b8ae7cea70521753e9 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Sat, 29 Jun 2013 11:12:41 -0700
+Subject: [RHEL7 libiscsi PATCH 12/18] bump ABI version
+
+ABI was not preserved between 1.7.0 and 1.9.0.  It was also bumped
+further after 1.9.0, so I made the upstream patch go to 3 and
+reserved 2 for Fedora/RHEL.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(see upstream commit d4a6e4b3e3c6becf507158b8ae7cea70521753e9)
+---
+diff --git a/Makefile.am b/Makefile.am
+index 50dfe11..4ccb52c 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -37,7 +37,7 @@ if !HAVE_LIBGCRYPT
+ lib_libiscsi_la_SOURCES += lib/md5.c
+ endif
+ 
+-SONAME=$(firstword $(subst ., ,$(VERSION)))
++SONAME=2
+ SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION)))
+ lib_libiscsi_la_LDFLAGS = \
+ 	-version-info $(SONAME):$(SOREL):0 -bindir $(bindir) -no-undefined \
diff --git a/SOURCES/0013-disable-ld_iscsi.patch b/SOURCES/0013-disable-ld_iscsi.patch
new file mode 100644
index 0000000..abc7126
--- /dev/null
+++ b/SOURCES/0013-disable-ld_iscsi.patch
@@ -0,0 +1,23 @@
+From dfb8fb325b5a3b28c08e3699575441d437ec1863 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Sat, 29 Jun 2013 11:12:41 -0700
+Subject: [RHEL7 libiscsi PATCH 13/18] disable ld_iscsi.so
+
+This is a LD_PRELOAD trick that we don't want to support, disable it.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(not upstream)
+---
+diff --git a/Makefile.am b/Makefile.am
+index 50dfe11..1a76d12 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -320,7 +320,7 @@ bin/ld_iscsi.o: src/bin_ld_iscsi-ld_iscsi.o lib/libiscsi_convenience.la
+ 	$(LIBTOOL) --mode=link $(CC) -o $@ $^
+ 
+ # 3) Manually create the .so file.
+-bin_SCRIPTS = bin/ld_iscsi.so
++#bin_SCRIPTS = bin/ld_iscsi.so
+ bin/ld_iscsi.so: bin/ld_iscsi.o
+ 	$(CC) -shared -o bin/ld_iscsi.so bin/ld_iscsi.o -ldl
+ endif
diff --git a/SOURCES/0014-fix-another-aliasing-problem.patch b/SOURCES/0014-fix-another-aliasing-problem.patch
new file mode 100644
index 0000000..0816c0a
--- /dev/null
+++ b/SOURCES/0014-fix-another-aliasing-problem.patch
@@ -0,0 +1,30 @@
+From dfb8fb325b5a3b28c08e3699575441d437ec1863 Mon Sep 17 00:00:00 2001
+Author: Paolo Bonzini <pbonzini@redhat.com>
+Date:   Fri Aug 2 14:07:42 2013 +0200
+Subject: [RHEL7 libiscsi PATCH 14/18] fix another aliasing problem
+
+scsi_set_uint64 should just use scsi_set_uint32, similar to
+what scsi_get_uint64 does.  This avoids problems on architectures
+where "uint32_t" requires more alignment than "char", e.g. ARM.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 31a3aeb0e0167401a7c10f4cba95a72697f907c0)
+
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index 0989f0f..1bb03af 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -300,11 +300,11 @@ scsi_set_uint64(unsigned char *c, uint64_t v)
+ 	uint32_t val;
+ 
+ 	val = (v >> 32) & 0xffffffff;
+-	*(uint32_t *)c = htonl(val);
++	scsi_set_uint32(c, val);
+ 
+ 	c += 4;
+ 	val = v & 0xffffffff;
+-	*(uint32_t *)c = htonl(val);
++	scsi_set_uint32(c, val);
+ }
+ 
+ inline void
diff --git a/SOURCES/0015-fix-arm-aliasing-problem.patch b/SOURCES/0015-fix-arm-aliasing-problem.patch
new file mode 100644
index 0000000..adbfb77
--- /dev/null
+++ b/SOURCES/0015-fix-arm-aliasing-problem.patch
@@ -0,0 +1,174 @@
+From 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Sat, 18 May 2013 13:56:02 -0700
+Subject: [RHEL7 libiscsi PATCH 15/18] TESTS: Add some REPORT SUPPORTED OPCODES tests
+
+Add a simple test that it works or is not implemented.
+
+Add a RCTD test to verify that with this flag clear we get command descriptors without CTDP set  and with it set we get command descriptors with CTDP set and a timeout descriptor
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c)
+
+Fixes these errors in ARM compilation:
+
+lib/scsi-lowlevel.c: In function 'scsi_maintenancein_datain_unmarshall':
+lib/scsi-lowlevel.c:862:12: error: cast increases required alignment of target type [-Werror=cast-align]
+   datain = (struct scsi_command_descriptor *)&task->datain.data[4];
+            ^
+lib/scsi-lowlevel.c:876:11: error: cast increases required alignment of target type [-Werror=cast-align]
+    desc = (struct scsi_command_descriptor *)((char *)desc + desc_size);
+           ^
+lib/scsi-lowlevel.c:877:13: error: cast increases required alignment of target type [-Werror=cast-align]
+    datain = (struct scsi_command_descriptor *)((char *)datain + desc_size);
+             ^
+---
+ include/scsi-lowlevel.h                          | 60 +++++++-------
+ lib/scsi-lowlevel.c                              | 77 +++++++++---------
+
+diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h
+index 5693129..acdc936 100644
+--- a/include/scsi-lowlevel.h
++++ b/include/scsi-lowlevel.h
+@@ -739,24 +739,24 @@ struct scsi_get_lba_status {
+ 
+ struct scsi_op_timeout_descriptor {
+ 	uint16_t descriptor_length;
+-	uint8_t reserved;
+ 	uint8_t command_specific;
+ 	uint32_t nominal_processing_timeout;
+ 	uint32_t recommended_timeout;
+ 
+ };
+ struct scsi_command_descriptor {
+-	uint8_t op_code;
+-	uint8_t reserved1;
+-	uint16_t service_action;
+-	uint8_t reserved2;
+-	uint8_t reserved3;
+-	uint16_t cdb_length;
+-	struct scsi_op_timeout_descriptor to[0];
++	uint8_t opcode;
++	uint16_t sa;
++	uint8_t ctdp;
++	uint8_t servactv;
++	uint16_t cdb_len;
++
++	/* only present if CTDP==1 */
++	struct scsi_op_timeout_descriptor to;
+ };
+ 
+ struct scsi_report_supported_op_codes {
+-	uint32_t num_descriptors;
++	int num_descriptors;
+ 	struct scsi_command_descriptor descriptors[0];
+ };
+ 
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index 3c02ace..c091539 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -806,12 +806,6 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
+ 	}
+ }
+ 
+-static inline int
+-scsi_maintenancein_return_timeouts(const struct scsi_task *task)
+-{
+-	return task->cdb[2] & 0x80;
+-}
+-
+ static inline uint8_t
+ scsi_maintenancein_sa(const struct scsi_task *task)
+ {
+@@ -841,9 +835,7 @@ static void *
+ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
+ {
+ 	struct scsi_report_supported_op_codes *rsoc;
+-	struct scsi_command_descriptor *desc, *datain;
+-	uint32_t len, i;
+-	int return_timeouts, desc_size;
++	int len, i;
+ 
+ 	switch (scsi_maintenancein_sa(task)) {
+ 	case SCSI_REPORT_SUPPORTED_OP_CODES:
+@@ -852,37 +844,52 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
+ 		}
+ 
+ 		len = task_get_uint32(task, 0);
+-		rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len);
++		/* len / 8 is not always correct since if CTDP==1 then the
++		 * descriptor is 20 bytes in size intead of 8.
++		 * It doesnt matter here though since it just means we would
++		 * allocate more descriptors at the end of the structure than
++		 * we strictly need. This avoids having to traverse the
++		 * datain buffer twice.
++		 */
++		rsoc = scsi_malloc(task,
++			offsetof(struct scsi_report_supported_op_codes,
++				 descriptors) +
++			len / 8 * sizeof(struct scsi_command_descriptor));
+ 		if (rsoc == NULL) {
+ 			return NULL;
+ 		}
+-		/* Does the descriptor include command timeout info? */
+-		return_timeouts = scsi_maintenancein_return_timeouts(task);
+ 
+-		/* Size of descriptor depends on whether timeout included. */
+-		desc_size = sizeof (struct scsi_command_descriptor);
+-		if (return_timeouts) {
+-			desc_size += sizeof (struct scsi_op_timeout_descriptor);
+-		}
+-		rsoc->num_descriptors = len / desc_size;
+-
+-		desc = &rsoc->descriptors[0];
+-		datain = (struct scsi_command_descriptor *)&task->datain.data[4];
+-
+-		for (i=0; i < rsoc->num_descriptors; i++) {
+-			desc->op_code = datain->op_code;
+-			desc->service_action = ntohs(datain->service_action);
+-			desc->cdb_length =  ntohs(datain->cdb_length);
+-			if (return_timeouts) {
+-				desc->to[0].descriptor_length = ntohs(datain->to[0].descriptor_length);
+-				desc->to[0].command_specific = datain->to[0].command_specific;
+-				desc->to[0].nominal_processing_timeout
+-					= ntohl(datain->to[0].nominal_processing_timeout);
+-				desc->to[0].recommended_timeout
+-					= ntohl(datain->to[0].recommended_timeout);
++		rsoc->num_descriptors = 0;
++		i = 4;
++		while (len >= 8) {
++			struct scsi_command_descriptor *desc;
++			
++			desc = &rsoc->descriptors[rsoc->num_descriptors++];
++			desc->opcode = task_get_uint8(task, i);
++			desc->sa = task_get_uint16(task, i + 2);
++			desc->ctdp = !!(task_get_uint8(task, i + 5) & 0x02);
++			desc->servactv = !!(task_get_uint8(task, i + 5) & 0x01);
++			desc->cdb_len = task_get_uint16(task, i + 6);
++
++			len -= 8;
++			i += 8;
++
++			/* No tiemout description */
++			if (!desc->ctdp) {
++				continue;
+ 			}
+-			desc = (struct scsi_command_descriptor *)((char *)desc + desc_size);
+-			datain = (struct scsi_command_descriptor *)((char *)datain + desc_size);
++
++			desc->to.descriptor_length =
++				task_get_uint16(task, i);
++			desc->to.command_specific =
++				task_get_uint8(task, i + 3);
++			desc->to.nominal_processing_timeout =
++				task_get_uint32(task, i + 4);
++			desc->to.recommended_timeout =
++				task_get_uint32(task, i + 8);
++
++			len -= desc->to.descriptor_length + 2;
++			i += desc->to.descriptor_length + 2;
+ 		}
+ 
+ 		return rsoc;
+
diff --git a/SOURCES/0016-avoid-casting-struct-sockaddr.patch b/SOURCES/0016-avoid-casting-struct-sockaddr.patch
new file mode 100644
index 0000000..afcf1cf
--- /dev/null
+++ b/SOURCES/0016-avoid-casting-struct-sockaddr.patch
@@ -0,0 +1,78 @@
+From 73ce7f40c81f7ef2647abe18df8f14c35c086c7e Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Fri, 2 Aug 2013 14:19:29 +0200
+Subject: [RHEL7 libiscsi PATCH 16/18] avoid casting struct sockaddr
+
+On ARM, this produces a warning.  Use a union instead.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 73ce7f40c81f7ef2647abe18df8f14c35c086c7e)
+---
+ lib/socket.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/lib/socket.c b/lib/socket.c
+index 5d98783..2c65a4a 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -171,6 +171,12 @@ int set_tcp_syncnt(struct iscsi_context *iscsi)
+ 	return 0;
+ }
+ 
++union socket_address {
++	struct sockaddr_in sin;
++	struct sockaddr_in6 sin6;
++	struct sockaddr sa;
++};
++
+ int
+ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
+ 		    iscsi_command_cb cb, void *private_data)
+@@ -179,6 +185,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
+ 	char *str;
+ 	char *addr, *host;
+ 	struct addrinfo *ai = NULL;
++	union socket_address sa;
+ 	int socksize;
+ 
+ 	ISCSI_LOG(iscsi, 2, "connecting to portal %s",portal);
+@@ -238,19 +245,22 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
+  	}
+ 	iscsi_free(iscsi, addr);
+ 
++	memset(&sa, 0, sizeof(sa));
+ 	switch (ai->ai_family) {
+ 	case AF_INET:
+ 		socksize = sizeof(struct sockaddr_in);
+-		((struct sockaddr_in *)(ai->ai_addr))->sin_port = htons(port);
++		memcpy(&sa.sin, ai->ai_addr, socksize);
++		sa.sin.sin_port = htons(port);
+ #ifdef HAVE_SOCK_SIN_LEN
+-		((struct sockaddr_in *)(ai->ai_addr))->sin_len = socksize;
++		sa.sin.sin_len = socksize;
+ #endif
+ 		break;
+ 	case AF_INET6:
+ 		socksize = sizeof(struct sockaddr_in6);
+-		((struct sockaddr_in6 *)(ai->ai_addr))->sin6_port = htons(port);
++		memcpy(&sa.sin6, ai->ai_addr, socksize);
++		sa.sin6.sin6_port = htons(port);
+ #ifdef HAVE_SOCK_SIN_LEN
+-		((struct sockaddr_in6 *)(ai->ai_addr))->sin6_len = socksize;
++		sa.sin6.sin6_len = socksize;
+ #endif
+ 		break;
+ 	default:
+@@ -316,7 +325,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
+ 		ISCSI_LOG(iscsi,3,"TCP_NODELAY set to 1");
+ 	}
+ 
+-	if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
++	if (connect(iscsi->fd, &sa.sa, socksize) != 0
+ 	    && errno != EINPROGRESS) {
+ 		iscsi_set_error(iscsi, "Connect failed with errno : "
+ 				"%s(%d)", strerror(errno), errno);
+-- 
+1.8.1.4
+
diff --git a/SOURCES/0018-cleanup-rename-pdu-written.patch b/SOURCES/0018-cleanup-rename-pdu-written.patch
new file mode 100644
index 0000000..7bb9c0e
--- /dev/null
+++ b/SOURCES/0018-cleanup-rename-pdu-written.patch
@@ -0,0 +1,91 @@
+From 6cb88eb0ce8faa4b417c3abd1a9b09d4f707037c Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+Date: Sun, 4 Aug 2013 17:27:29 -0700
+Subject: [RHEL7 libiscsi PATCH 17/18] Cleanup: rename pdu->written -> pdu->outdata_written
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 6cb88eb0ce8faa4b417c3abd1a9b09d4f707037c)
+---
+ include/iscsi-private.h |  4 ++--
+ lib/connect.c           |  2 +-
+ lib/socket.c            | 16 ++++++----------
+ 3 files changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/include/iscsi-private.h b/include/iscsi-private.h
+index df20702..d386988 100644
+--- a/include/iscsi-private.h
++++ b/include/iscsi-private.h
+@@ -221,9 +221,9 @@ struct iscsi_pdu {
+ 	iscsi_command_cb callback;
+ 	void *private_data;
+ 
+-	int written;
+-
+ 	struct iscsi_data outdata; /* Header for PDU to send */
++	size_t outdata_written;	   /* How much of the header we have written */
++
+ 	uint32_t out_offset;       /* Offset into data-out iovector */
+ 	uint32_t out_len;          /* Amount of data to sent starting at out_offset */
+ 	uint32_t out_written;      /* Number of bytes written to socket */
+diff --git a/lib/connect.c b/lib/connect.c
+index 7790253..732e0cf 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -343,7 +343,7 @@ try_again:
+ 		iscsi_pdu_set_expstatsn(pdu, iscsi->statsn);
+ 		iscsi->statsn++;
+ 
+-		pdu->written = 0;
++		pdu->outdata_written = 0;
+ 		pdu->out_written = 0;
+ 		iscsi_add_to_outqueue(iscsi, pdu);
+ 	}
+diff --git a/lib/socket.c b/lib/socket.c
+index 375cfd2..f94bb1c 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -596,8 +596,6 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
+ 	}
+ 
+ 	while (iscsi->outqueue != NULL || iscsi->outqueue_current != NULL) {
+-		ssize_t total;
+-
+ 		if (iscsi->outqueue_current == NULL) {
+ 			if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
+ 				/* stop sending. maxcmdsn is reached */
+@@ -616,15 +614,13 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
+ 		}
+ 
+ 		pdu = iscsi->outqueue_current;
+-
+-		total = pdu->outdata.size;
+-		total = (total + 3) & 0xfffffffc;
++		pdu->outdata.size = (pdu->outdata.size + 3) & 0xfffffffc;
+ 
+ 		/* Write header and any immediate data */
+-		if (pdu->written < total) {
++		if (pdu->outdata_written < pdu->outdata.size) {
+ 			count = send(iscsi->fd,
+-				     pdu->outdata.data + pdu->written,
+-				     total - pdu->written,
++				     pdu->outdata.data + pdu->outdata_written,
++				     pdu->outdata.size - pdu->outdata_written,
+ 				     0);
+ 			if (count == -1) {
+ 				if (errno == EAGAIN || errno == EWOULDBLOCK) {
+@@ -634,10 +630,10 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
+ 						"socket :%d", errno);
+ 				return -1;
+ 			}
+-			pdu->written += count;
++			pdu->outdata_written += count;
+ 		}
+ 		/* if we havent written the full header yet. */
+-		if (pdu->written != total) {
++		if (pdu->outdata_written != pdu->outdata.size) {
+ 			return 0;
+ 		}
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0019-fix-iovec-short-reads.patch b/SOURCES/0019-fix-iovec-short-reads.patch
new file mode 100644
index 0000000..4f7b7c0
--- /dev/null
+++ b/SOURCES/0019-fix-iovec-short-reads.patch
@@ -0,0 +1,155 @@
+From 73b0d4777f90ec6e1f0a81f9e4c21830fb58c9b7 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Subject: [RHEL7 libiscsi PATCH 18/18] Ignore padding when an iovector is supplied
+
+The iSCSI protocol adds padding to a data packet if the data size is not
+a multiple of four.  The iovector provided by QEMU does not include such
+padding, and libiscsi then complains that there was a protocol error.
+This patch fixes this by reading the padding in a separate "recv"
+system call.  These packets anyway do not happen in the data path,
+where the packet size is a multiple of 512.
+
+Similarly, we need to write padding after an outgoing data packet.
+
+This fixes QEMU's scsi-generic backend, which triggered the problem when
+the target sent a 66-byte INQUIRY response.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry-picked from upstream commit 73b0d4777f90ec6e1f0a81f9e4c21830fb58c9b7)
+---
+diff --git a/include/iscsi-private.h b/include/iscsi-private.h
+index e9b9e7e..6cc8a20 100644
+--- a/include/iscsi-private.h
++++ b/include/iscsi-private.h
+@@ -261,6 +261,7 @@ struct scsi_task;
+ void iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task);
+ 
+ int iscsi_get_pdu_data_size(const unsigned char *hdr);
++int iscsi_get_pdu_padding_size(const unsigned char *hdr);
+ int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in);
+ 
+ int iscsi_process_login_reply(struct iscsi_context *iscsi,
+diff --git a/lib/pdu.c b/lib/pdu.c
+index f53490a..043a986 100644
+--- a/lib/pdu.c
++++ b/lib/pdu.c
+@@ -217,11 +217,22 @@ iscsi_get_pdu_data_size(const unsigned char *hdr)
+ 	int size;
+ 
+ 	size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
+-	size = (size+3) & 0xfffffffc;
+ 
+ 	return size;
+ }
+ 
++
++int
++iscsi_get_pdu_padding_size(const unsigned char *hdr)
++{
++	int data_size, padded_size;
++
++	data_size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
++	padded_size = (data_size+3) & 0xfffffffc;
++
++	return padded_size - data_size;
++}
++
+ enum iscsi_reject_reason {
+ 	ISCSI_REJECT_RESERVED                 = 0x01,
+ 	ISCSI_REJECT_DATA_DIGEST_ERROR        = 0x02,
+diff --git a/lib/socket.c b/lib/socket.c
+index 13020ee..7a668c2 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -479,7 +479,7 @@ static int
+ iscsi_read_from_socket(struct iscsi_context *iscsi)
+ {
+ 	struct iscsi_in_pdu *in;
+-	ssize_t data_size, count;
++	ssize_t data_size, count, padding_size;
+ 
+ 	if (iscsi->incoming == NULL) {
+ 		iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu));
+@@ -516,31 +516,36 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
+ 		return 0;
+ 	}
+ 
+-	data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
++	padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
++	data_size = iscsi_get_pdu_data_size(&in->hdr[0]) + padding_size;
++
+ 	if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) {
+ 		iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
+ 		return -1;
+ 	}
+ 	if (data_size != 0) {
+-		unsigned char *buf = NULL;
++		unsigned char padding_buf[3];
++		unsigned char *buf = padding_buf;
+ 		struct scsi_iovector * iovector_in;
+ 
+ 		count = data_size - in->data_pos;
+ 
+ 		/* first try to see if we already have a user buffer */
+ 		iovector_in = iscsi_get_scsi_task_iovector_in(iscsi, in);
+-		if (iovector_in != NULL) {
++		if (iovector_in != NULL && count > padding_size) {
+ 			uint32_t offset = scsi_get_uint32(&in->hdr[40]);
+-			count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count, 0);
++			count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count - padding_size, 0);
+ 		} else {
+-			if (in->data == NULL) {
+-				in->data = iscsi_malloc(iscsi, data_size);
++			if (iovector_in == NULL) {
+ 				if (in->data == NULL) {
+-					iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
+-					return -1;
++					in->data = iscsi_malloc(iscsi, data_size);
++					if (in->data == NULL) {
++						iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
++						return -1;
++					}
+ 				}
++				buf = &in->data[in->data_pos];
+ 			}
+-			buf = &in->data[in->data_pos];
+ 			count = recv(iscsi->fd, buf, count, 0);
+ 		}
+ 		
+@@ -586,6 +591,8 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
+ {
+ 	ssize_t count;
+ 	struct iscsi_pdu *pdu;
++	static char padding_buf[3];
++	size_t total;
+ 
+ 	if (iscsi->fd == -1) {
+ 		iscsi_set_error(iscsi, "trying to write but not connected");
+@@ -663,6 +669,27 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
+ 			pdu->out_written += count;
+ 		}
+ 
++		total = pdu->out_len;
++		total = (total + 3) & 0xfffffffc;
++
++		/* Write padding */
++		if (pdu->out_written < total) {
++			count = send(iscsi->fd, padding_buf, total - pdu->out_written, 0);
++			if (count == -1) {
++				if (errno == EAGAIN || errno == EWOULDBLOCK) {
++					return 0;
++				}
++				iscsi_set_error(iscsi, "Error when writing to "
++						"socket :%d", errno);
++				return -1;
++			}
++			pdu->out_written += count;
++		}
++		/* if we havent written the full padding yet. */
++		if (pdu->out_written != total) {
++			return 0;
++		}
++
+ 		if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
+ 			iscsi_free_pdu(iscsi, pdu);
+ 		}
diff --git a/SOURCES/0020-iscsi_reconnect-Fix-a-use-after-free.patch b/SOURCES/0020-iscsi_reconnect-Fix-a-use-after-free.patch
new file mode 100644
index 0000000..e7b6075
--- /dev/null
+++ b/SOURCES/0020-iscsi_reconnect-Fix-a-use-after-free.patch
@@ -0,0 +1,63 @@
+iscsi_reconnect: Fix a use-after-free
+
+Message-id: <1383729402-27559-2-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55496
+O-Subject: [PATCH 01/11] iscsi_reconnect: Fix a use-after-free
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+This patch fixes the following Valgrind complaint:
+
+Invalid read of size 4
+   at 0x524A858: iscsi_reconnect (connect.c:378)
+   by 0x5258794: iscsi_service (socket.c:707)
+   by 0x52599C4: event_loop (sync.c:67)
+   by 0x525AFD7: iscsi_reserve6_sync (sync.c:1096)
+   by 0x40A40A: reserve6 (iscsi-support.c:3291)
+   by 0x422C95: test_reserve6_target_warm_reset (test_reserve6_target_warm_reset.c:39)
+   by 0x503B05F: ??? (in /usr/lib/libcunit.so.1.0.1)
+   by 0x503B375: ??? (in /usr/lib/libcunit.so.1.0.1)
+   by 0x503B69F: CU_run_all_tests (in /usr/lib/libcunit.so.1.0.1)
+   by 0x403171: main (iscsi-test-cu.c:1258)
+ Address 0x6443958 is 3,032 bytes inside a block of size 4,120 free'd
+   at 0x4C2B83A: free (vg_replace_malloc.c:468)
+   by 0x524A846: iscsi_reconnect (connect.c:374)
+   by 0x5258794: iscsi_service (socket.c:707)
+   by 0x52599C4: event_loop (sync.c:67)
+   by 0x525AFD7: iscsi_reserve6_sync (sync.c:1096)
+   by 0x40A40A: reserve6 (iscsi-support.c:3291)
+   by 0x422C95: test_reserve6_target_warm_reset (test_reserve6_target_warm_reset.c:39)
+   by 0x503B05F: ??? (in /usr/lib/libcunit.so.1.0.1)
+   by 0x503B375: ??? (in /usr/lib/libcunit.so.1.0.1)
+   by 0x503B69F: CU_run_all_tests (in /usr/lib/libcunit.so.1.0.1)
+   by 0x403171: main (iscsi-test-cu.c:1258)
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+(cherry picked from commit 4653cd8df4c14f4eea37b6ce66277330774dd3d5)
+---
+ lib/connect.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+diff --git a/lib/connect.c b/lib/connect.c
+index bcb9d3b..0d4c957 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -356,13 +356,13 @@ try_again:
+ 	iscsi->mallocs+=old_iscsi->mallocs;
+ 	iscsi->frees+=old_iscsi->frees;
+ 
++	ISCSI_LOG(iscsi, 2, "reconnect was successful");
++
+ 	memcpy(old_iscsi, iscsi, sizeof(struct iscsi_context));
+-	memset(iscsi, 0, sizeof(struct iscsi_context));
+ 	free(iscsi);
+ 
+ 	old_iscsi->is_reconnecting = 0;
+ 	old_iscsi->last_reconnect = time(NULL);
+-	ISCSI_LOG(iscsi, 2, "reconnect was successful");
+ 
+ 	return 0;
+ }
diff --git a/SOURCES/0021-Dont-reference-pdu-after-it-has-been-freed.patch b/SOURCES/0021-Dont-reference-pdu-after-it-has-been-freed.patch
new file mode 100644
index 0000000..eda6fb1
--- /dev/null
+++ b/SOURCES/0021-Dont-reference-pdu-after-it-has-been-freed.patch
@@ -0,0 +1,38 @@
+Dont reference *pdu after it has been freed
+
+Message-id: <1383729402-27559-3-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55497
+O-Subject: [PATCH 02/11] Dont reference *pdu after it has been freed
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+
+(cherry picked from commit 804c5b02112d84c79460e7b2a01fe42f0ca5e687)
+---
+ lib/iscsi-command.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
+index e52612d..95127a5 100644
+--- a/lib/iscsi-command.c
++++ b/lib/iscsi-command.c
+@@ -1636,7 +1636,7 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
+ {
+ 	struct iscsi_pdu *pdu;
+ 
+-	for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
++	while ((pdu = iscsi->waitpdu)) {
+ 		SLIST_REMOVE(&iscsi->waitpdu, pdu);
+ 		if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) {
+ 			pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
+@@ -1644,7 +1644,7 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
+ 		}
+ 		iscsi_free_pdu(iscsi, pdu);
+ 	}
+-	for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
++	while ((pdu = iscsi->outqueue)) {
+ 		SLIST_REMOVE(&iscsi->outqueue, pdu);
+ 		if ( !(pdu->flags & ISCSI_PDU_NO_CALLBACK)) {
+ 			pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
diff --git a/SOURCES/0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch b/SOURCES/0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch
new file mode 100644
index 0000000..eb05275
--- /dev/null
+++ b/SOURCES/0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch
@@ -0,0 +1,35 @@
+lib: Make scsi_free_scsi_task() accept a NULL task pointer
+
+Message-id: <1383729402-27559-4-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55498
+O-Subject: [PATCH 03/11] lib: Make scsi_free_scsi_task() accept a NULL task pointer
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+Several cleanup paths can be simplified if it is allowed to pass a
+NULL pointer to scsi_free_scsi_task(). Hence modify this function
+such that it returns immediately if passed a NULL task pointer.
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+(cherry picked from commit afa076b5377cff7e1b4096965849e7939c399af1)
+---
+ lib/scsi-lowlevel.c | 3 +++
+ 1 file changed, 3 insertions(+)
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index ce9f904..0f97a79 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -50,6 +50,9 @@ scsi_free_scsi_task(struct scsi_task *task)
+ {
+ 	struct scsi_allocated_memory *mem;
+ 
++	if (!task)
++		return;
++
+ 	while ((mem = task->mem)) {
+ 		   SLIST_REMOVE(&task->mem, mem);
+ 		   free(mem);
diff --git a/SOURCES/0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch b/SOURCES/0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch
new file mode 100644
index 0000000..b9d538b
--- /dev/null
+++ b/SOURCES/0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch
@@ -0,0 +1,103 @@
+lib: Fix a memory leak in scsi_cdb_persistent_reserve_out()
+
+Message-id: <1383729402-27559-5-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55499
+O-Subject: [PATCH 04/11] lib: Fix a memory leak in scsi_cdb_persistent_reserve_out()
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+If scsi_cdb_persistent_reserve_out() succeeds a call to
+scsi_free_scsi_task() won't free any memory allocated with scsi_malloc()
+in this function because the memset() call in this function overwrites
+the task->mem pointer. Move the memset() call up such that it doesn't
+clear task->mem. This makes it possible for the caller of this function
+to free the memory allocated by this function by calling
+scsi_free_scsi_task(). Merge the error handling code such that the code
+for freeing memory only occurs once.
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+(cherry picked from commit 3fdc3f2327939174b1691eca6a55915cc3e08b8b)
+---
+        The problem reported by Coverity is that scsi_malloc accesses
+        task->mem, which is uninitialized.
+
+ lib/scsi-lowlevel.c | 37 +++++++++++++++----------------------
+ 1 file changed, 15 insertions(+), 22 deletions(-)
+diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c
+index 0f97a79..28d0a08 100644
+--- a/lib/scsi-lowlevel.c
++++ b/lib/scsi-lowlevel.c
+@@ -1874,15 +1874,14 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
+ 	int xferlen;
+ 
+ 	task = malloc(sizeof(struct scsi_task));
+-	if (task == NULL) {
+-		return NULL;
+-	}
++	if (task == NULL)
++		goto err;
++
++	memset(task, 0, sizeof(struct scsi_task));
+ 
+ 	iov = scsi_malloc(task, sizeof(struct scsi_iovec));
+-	if (iov == NULL) {
+-		free(task);
+-		return NULL;
+-	}
++	if (iov == NULL)
++		goto err;
+ 
+ 	switch(sa) {
+ 	case SCSI_PERSISTENT_RESERVE_REGISTER:
+@@ -1896,11 +1895,8 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
+ 
+ 		xferlen = 24;
+ 		buf = scsi_malloc(task, xferlen);
+-		if (buf == NULL) {
+-			free(task);
+-			free(iov);
+-			return NULL;
+-		}
++		if (buf == NULL)
++			goto err;
+ 		
+ 		memset(buf, 0, xferlen);
+ 		scsi_set_uint64(&buf[0], basic->reservation_key);
+@@ -1917,19 +1913,12 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
+ 		break;
+ 	case SCSI_PERSISTENT_RESERVE_REGISTER_AND_MOVE:
+ 		/* XXX FIXME */
+-		free(task);
+-		free(iov);
+-		return NULL;
++		goto err;
+ 	default:
+-		free(task);
+-		free(iov);
+-		return NULL;
++		goto err;
+ 	}
+ 
+-
+-	memset(task, 0, sizeof(struct scsi_task));
+-	task->cdb[0]   = SCSI_OPCODE_PERSISTENT_RESERVE_OUT;
+-
++	task->cdb[0] = SCSI_OPCODE_PERSISTENT_RESERVE_OUT;
+ 	task->cdb[1] |= sa & 0x1f;
+ 	task->cdb[2] = ((scope << 4) & 0xf0) | (type & 0x0f);
+ 	
+@@ -1944,6 +1933,10 @@ scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persis
+ 	scsi_task_set_iov_out(task, iov, 1);
+ 
+ 	return task;
++
++err:
++	scsi_free_scsi_task(task);
++	return NULL;
+ }
+ 
+ /*
diff --git a/SOURCES/0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch b/SOURCES/0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch
new file mode 100644
index 0000000..aaa9e8e
--- /dev/null
+++ b/SOURCES/0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch
@@ -0,0 +1,77 @@
+reconnect: do not initialize iscsi to old_iscsi, use old_iscsi if appropriate
+
+Message-id: <1383729402-27559-6-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55500
+O-Subject: [PATCH 05/11] reconnect: do not initialize iscsi to old_iscsi, use old_iscsi if appropriate
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Makes it clearer that logging has to be done on the existing context,
+since the "iscsi" pointer will not survive iscsi_reconnect.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit c3e8d0c9454835074ebcc6971618b2e71bb948c4)
+
+Conflicts:
+	lib/connect.c
+---
+ lib/connect.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+diff --git a/lib/connect.c b/lib/connect.c
+index 0d4c957..d6a8759 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -217,22 +217,22 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi)
+ 
+ int iscsi_reconnect(struct iscsi_context *old_iscsi)
+ {
+-	struct iscsi_context *iscsi = old_iscsi;
++	struct iscsi_context *iscsi;
+ 
+ 	/* if there is already a deferred reconnect do not try again */
+-	if (iscsi->reconnect_deferred) {
+-		ISCSI_LOG(iscsi, 2, "reconnect initiated, but reconnect is already deferred");
++	if (old_iscsi->reconnect_deferred) {
++		ISCSI_LOG(old_iscsi, 2, "reconnect initiated, but reconnect is already deferred");
+ 		return -1;
+ 	}
+ 
+-	ISCSI_LOG(iscsi, 2, "reconnect initiated");
++	ISCSI_LOG(old_iscsi, 2, "reconnect initiated");
+ 
+ 	/* This is mainly for tests, where we do not want to automatically
+ 	   reconnect but rather want the commands to fail with an error
+ 	   if the target drops the session.
+ 	 */
+-	if (iscsi->no_auto_reconnect) {
+-		iscsi_defer_reconnect(iscsi);
++	if (old_iscsi->no_auto_reconnect) {
++		iscsi_defer_reconnect(old_iscsi);
+ 		return 0;
+ 	}
+ 
+@@ -288,7 +288,7 @@ try_again:
+ 		if (backoff > 30) {
+ 			backoff=30;
+ 		}
+-		ISCSI_LOG(iscsi, 1, "reconnect try %d failed, waiting %d seconds",retry,backoff);
++		ISCSI_LOG(old_iscsi, 1, "reconnect try %d failed, waiting %d seconds", retry, backoff);
+ 		iscsi_destroy_context(iscsi);
+ 		sleep(backoff);
+ 		retry++;
+@@ -356,11 +356,11 @@ try_again:
+ 	iscsi->mallocs+=old_iscsi->mallocs;
+ 	iscsi->frees+=old_iscsi->frees;
+ 
+-	ISCSI_LOG(iscsi, 2, "reconnect was successful");
+-
+ 	memcpy(old_iscsi, iscsi, sizeof(struct iscsi_context));
+ 	free(iscsi);
+ 
++	ISCSI_LOG(old_iscsi, 2, "reconnect was successful");
++
+ 	old_iscsi->is_reconnecting = 0;
+ 	old_iscsi->last_reconnect = time(NULL);
+ 
diff --git a/SOURCES/0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch b/SOURCES/0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch
new file mode 100644
index 0000000..846b7d6
--- /dev/null
+++ b/SOURCES/0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch
@@ -0,0 +1,31 @@
+log failures (typically malloc) of iscsi_create_context during reconnect
+
+Message-id: <1383729402-27559-7-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55501
+O-Subject: [PATCH 06/11] log failures (typically malloc) of iscsi_create_context during reconnect
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 1acce4a94892ffc8fb75945fc2d2ee691b66a524)
+---
+ lib/connect.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+diff --git a/lib/connect.c b/lib/connect.c
+index d6a8759..cd3f336 100644
+--- a/lib/connect.c
++++ b/lib/connect.c
+@@ -245,6 +245,11 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
+ try_again:
+ 
+ 	iscsi = iscsi_create_context(old_iscsi->initiator_name);
++	if (!iscsi) {
++		ISCSI_LOG(old_iscsi, 2, "failed to create new context for reconnection");
++		return -1;
++	}
++
+ 	iscsi->is_reconnecting = 1;
+ 
+ 	iscsi_set_targetname(iscsi, old_iscsi->target_name);
diff --git a/SOURCES/0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch b/SOURCES/0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch
new file mode 100644
index 0000000..6567d52
--- /dev/null
+++ b/SOURCES/0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch
@@ -0,0 +1,27 @@
+exit after malloc failure when allocating sense data blob
+
+Message-id: <1383729402-27559-8-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55502
+O-Subject: [PATCH 07/11] exit after malloc failure when allocating sense data blob
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit dbaa0b4ea6a4ca11d279a4264457ccb1ad4f67ad)
+---
+ lib/iscsi-command.c | 1 +
+ 1 file changed, 1 insertion(+)
+diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
+index 95127a5..1191cd6 100644
+--- a/lib/iscsi-command.c
++++ b/lib/iscsi-command.c
+@@ -365,6 +365,7 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 		if (task->datain.data == NULL) {
+ 			iscsi_set_error(iscsi, "failed to allocate blob for "
+ 					"sense data");
++			break;
+ 		}
+ 		memcpy(task->datain.data, in->data, task->datain.size);
+ 
diff --git a/SOURCES/0027-do-not-test-arrays-against-NULL.patch b/SOURCES/0027-do-not-test-arrays-against-NULL.patch
new file mode 100644
index 0000000..a6779c5
--- /dev/null
+++ b/SOURCES/0027-do-not-test-arrays-against-NULL.patch
@@ -0,0 +1,79 @@
+do not test arrays against NULL
+
+Message-id: <1383729402-27559-9-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55503
+O-Subject: [PATCH 08/11] do not test arrays against NULL
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit fce94c81a3191a2ba884dcc7a5822b5776004b4f)
+---
+ lib/login.c                | 4 ++--
+ src/iscsi-inq.c            | 2 +-
+ src/iscsi-ls.c             | 2 +-
+ src/iscsi-readcapacity16.c | 2 +-
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+diff --git a/lib/login.c b/lib/login.c
+index 7a6b092..22a7408 100644
+--- a/lib/login.c
++++ b/lib/login.c
+@@ -802,7 +802,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
+ 	}
+ 
+ 	/* optional alias */
+-	if (iscsi->alias) {
++	if (iscsi->alias[0]) {
+ 		if (iscsi_login_add_alias(iscsi, pdu) != 0) {
+ 			iscsi_free_pdu(iscsi, pdu);
+ 			return -1;
+@@ -1097,7 +1097,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 		size -= len + 1;
+ 	}
+ 
+-	if (status == SCSI_STATUS_REDIRECT && iscsi->target_address) {
++	if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
+ 		ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);
+ 		pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL,
+ 				  pdu->private_data);
+diff --git a/src/iscsi-inq.c b/src/iscsi-inq.c
+index d694dad..a12b044 100644
+--- a/src/iscsi-inq.c
++++ b/src/iscsi-inq.c
+@@ -294,7 +294,7 @@ int main(int argc, const char *argv[])
+ 	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
+ 	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
+ 
+-	if (iscsi_url->user != NULL) {
++	if (iscsi_url->user[0]) {
+ 		if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
+ 			fprintf(stderr, "Failed to set initiator username and password\n");
+ 			exit(10);
+diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c
+index 3ffc9bc..10b0e8d 100644
+--- a/src/iscsi-ls.c
++++ b/src/iscsi-ls.c
+@@ -390,7 +390,7 @@ int main(int argc, const char *argv[])
+ 
+ 	iscsi_set_session_type(iscsi, ISCSI_SESSION_DISCOVERY);
+ 
+-	if (iscsi_url->user != NULL) {
++	if (iscsi_url->user[0]) {
+ 		state.username = iscsi_url->user;
+ 		state.password = iscsi_url->passwd;
+ 		if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
+diff --git a/src/iscsi-readcapacity16.c b/src/iscsi-readcapacity16.c
+index d286d70..79966ca 100644
+--- a/src/iscsi-readcapacity16.c
++++ b/src/iscsi-readcapacity16.c
+@@ -137,7 +137,7 @@ int main(int argc, const char *argv[])
+ 	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
+ 	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
+ 
+-	if (iscsi_url->user != NULL) {
++	if (iscsi_url->user[0]) {
+ 		if (iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
+ 			fprintf(stderr, "Failed to set initiator username and password\n");
+ 			exit(10);
diff --git a/SOURCES/0028-handle-bad-iscsi--fd-in-iscsi_service.patch b/SOURCES/0028-handle-bad-iscsi--fd-in-iscsi_service.patch
new file mode 100644
index 0000000..57db636
--- /dev/null
+++ b/SOURCES/0028-handle-bad-iscsi--fd-in-iscsi_service.patch
@@ -0,0 +1,40 @@
+handle bad iscsi->fd in iscsi_service
+
+Message-id: <1383729402-27559-10-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55504
+O-Subject: [PATCH 09/11] handle bad iscsi->fd in iscsi_service
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Just do nothing if the file descriptor is invalid.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit bb0e59055aeb69b0b035e2c2f848d8e82c96eade)
+---
+ lib/socket.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+diff --git a/lib/socket.c b/lib/socket.c
+index 8f7ebb2..78dfbfe 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -691,6 +691,9 @@ iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi)
+ int
+ iscsi_service(struct iscsi_context *iscsi, int revents)
+ {
++	if (iscsi->fd < 0)
++		return 0;
++
+ 	if (revents & POLLERR) {
+ 		int err = 0;
+ 		socklen_t err_size = sizeof(err);
+@@ -725,7 +728,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
+ 		return iscsi_service_reconnect_if_loggedin(iscsi);
+ 	}
+ 
+-	if (iscsi->is_connected == 0 && iscsi->fd != -1 && revents&POLLOUT) {
++	if (iscsi->is_connected == 0 && revents&POLLOUT) {
+ 		int err = 0;
+ 		socklen_t err_size = sizeof(err);
+ 		if (getsockopt(iscsi->fd, SOL_SOCKET, SO_ERROR,
diff --git a/SOURCES/0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch b/SOURCES/0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch
new file mode 100644
index 0000000..9b608c1
--- /dev/null
+++ b/SOURCES/0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch
@@ -0,0 +1,145 @@
+rework login and discovery code to avoid strlen beyond end of data
+
+Message-id: <1383729402-27559-11-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55505
+O-Subject: [PATCH 10/11] rework login and discovery code to avoid strlen beyond end of data
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Checking for the presence of the NUL character should be done
+without accessing beyond the PDU datain.  Use memchr instead
+of strlen, and compute the length only if a NUL character is
+actually there.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit bfde49756524bd3748234dc6dfa8015e37176e9b)
+
+Conflicts:
+	lib/login.c
+---
+ lib/discovery.c | 31 ++++++++++++++++++++-----------
+ lib/login.c     | 32 +++++++++++++++++++++-----------
+ 2 files changed, 41 insertions(+), 22 deletions(-)
+diff --git a/lib/discovery.c b/lib/discovery.c
+index 1ddf8ef..7396e71 100644
+--- a/lib/discovery.c
++++ b/lib/discovery.c
+@@ -112,25 +112,34 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 			      pdu->private_data);
+ 		return -1;
+ 	}
++	if (size == 0) {
++		iscsi_set_error(iscsi, "size == 0 when parsing "
++				"discovery data");
++		pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
++			      pdu->private_data);
++		return -1;
++	}
+ 
+-	while (size > 0) {
++	do {
++		unsigned char *end;
+ 		int len;
+ 
+-		len = strlen((char *)ptr);
+-
+-		if (len == 0) {
+-			break;
+-		}
+-
+-		if (len > size) {
+-			iscsi_set_error(iscsi, "len > size when parsing "
+-					"discovery data %d>%d", len, size);
++		end = memchr(ptr, 0, size);
++		if (end == NULL) {
++			iscsi_set_error(iscsi, "NUL not found after offset %td "
++					"when parsing discovery data",
++					ptr - in->data);
+ 			pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ 				      pdu->private_data);
+ 			iscsi_free_discovery_addresses(iscsi, targets);
+ 			return -1;
+ 		}
+ 
++		len = end - ptr;
++		if (len == 0) {
++			break;
++		}
++
+ 		/* parse the strings */
+ 		if (!strncmp((char *)ptr, "TargetName=", 11)) {
+ 			struct iscsi_discovery_address *target;
+@@ -181,7 +190,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 
+ 		ptr  += len + 1;
+ 		size -= len + 1;
+-	}
++	} while (size > 0);
+ 
+ 	pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
+ 	iscsi_free_discovery_addresses(iscsi, targets);
+diff --git a/lib/login.c b/lib/login.c
+index 22a7408..8b696b0 100644
+--- a/lib/login.c
++++ b/lib/login.c
+@@ -1000,29 +1000,39 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 		iscsi->maxcmdsn = maxcmdsn;
+ 	}
+ 	
++	if (size == 0) {
++	       iscsi_set_error(iscsi, "size == 0 when parsing "
++			       "login data");
++	       pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
++			     pdu->private_data);
++	       return -1;
++	}
++
+ 	/* XXX here we should parse the data returned in case the target
+ 	 * renegotiated some some parameters.
+ 	 *  we should also do proper handshaking if the target is not yet
+ 	 * prepared to transition to the next stage
+ 	 */
+ 
+-	while (size > 0) {
++	do {
++		char *end;
+ 		int len;
+ 
+-		len = strlen(ptr);
+-
+-		if (len == 0) {
+-			break;
+-		}
+-
+-		if (len > size) {
+-			iscsi_set_error(iscsi, "len > size when parsing "
+-					"login data %d>%d", len, size);
++		end = memchr(ptr, 0, size);
++		if (end == NULL) {
++			iscsi_set_error(iscsi, "NUL not found after offset %td "
++					"when parsing login data",
++					(unsigned char *)ptr - in->data);
+ 			pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+ 				      pdu->private_data);
+ 			return -1;
+ 		}
+ 
++		len = end - ptr;
++		if (len == 0) {
++			break;
++		}
++
+ 		/* parse the strings */
+ 		if (!strncmp(ptr, "TargetAddress=", 14)) {
+ 			strncpy(iscsi->target_address,ptr+14,MAX_STRING_SIZE);
+@@ -1095,7 +1105,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 
+ 		ptr  += len + 1;
+ 		size -= len + 1;
+-	}
++	} while (size > 0);
+ 
+ 	if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
+ 		ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);
diff --git a/SOURCES/0030-check-for-a-target-being-there-before-processing-TargetAddress.patch b/SOURCES/0030-check-for-a-target-being-there-before-processing-TargetAddress.patch
new file mode 100644
index 0000000..9602305
--- /dev/null
+++ b/SOURCES/0030-check-for-a-target-being-there-before-processing-TargetAddress.patch
@@ -0,0 +1,36 @@
+check for a target being there before processing TargetAddress
+
+Message-id: <1383729402-27559-12-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 55506
+O-Subject: [PATCH 11/11] check for a target being there before processing TargetAddress
+Bugzilla: 1026820
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Otherwise we access a NULL pointer.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 87ee6456217debfbb9a0180933ed84281e45a705)
+---
+ lib/discovery.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+diff --git a/lib/discovery.c b/lib/discovery.c
+index 7396e71..178faef 100644
+--- a/lib/discovery.c
++++ b/lib/discovery.c
+@@ -169,6 +169,14 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 			target->next = targets;
+ 			targets = target;
+ 		} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
++			if (targets == NULL || targets->target_address != NULL) {
++				iscsi_set_error(iscsi, "Invalid discovery "
++						"reply");
++				pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
++					      pdu->private_data);
++				iscsi_free_discovery_addresses(iscsi, targets);
++				return -1;
++			}
+ 			targets->target_address = iscsi_strdup(iscsi, (char *)ptr+14);
+ 			if (targets->target_address == NULL) {
+ 				iscsi_set_error(iscsi, "Failed to allocate "
diff --git a/SOURCES/0031-fix-CHAP-authentication.patch b/SOURCES/0031-fix-CHAP-authentication.patch
new file mode 100644
index 0000000..56ed127
--- /dev/null
+++ b/SOURCES/0031-fix-CHAP-authentication.patch
@@ -0,0 +1,89 @@
+fix CHAP authentication
+
+Message-id: <1386865659-20686-1-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 56264
+O-Subject: [RHEL7.0 libiscsi PATCH] fix CHAP authentication
+Bugzilla: 1032358
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Bandan Das <bsd@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Empty discovery and login packets are legal, and have the same behavior
+as packets with a single NUL in them.  Introduced by commit 94d73fc
+(Merge pull request #83 from bonzini/coverity, 2013-11-05).
+
+Reported-by: John Ferlan <jferlan@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+        See the rhvirt-patches message with ID
+        <1383729402-27559-11-git-send-email-pbonzini@redhat.com>
+
+ lib/discovery.c | 11 ++---------
+ lib/login.c     | 12 ++----------
+ 2 files changed, 4 insertions(+), 19 deletions(-)
+diff --git a/lib/discovery.c b/lib/discovery.c
+index 8301bea..2870bd6 100644
+--- a/lib/discovery.c
++++ b/lib/discovery.c
+@@ -118,15 +118,8 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 			      pdu->private_data);
+ 		return -1;
+ 	}
+-	if (size == 0) {
+-		iscsi_set_error(iscsi, "size == 0 when parsing "
+-				"discovery data");
+-		pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+-			      pdu->private_data);
+-		return -1;
+-	}
+ 
+-	do {
++	while (size > 0) {
+ 		unsigned char *end;
+ 		int len;
+ 
+@@ -204,7 +197,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 
+ 		ptr  += len + 1;
+ 		size -= len + 1;
+-	} while (size > 0);
++	}
+ 
+ 	pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
+ 	iscsi_free_discovery_addresses(iscsi, targets);
+diff --git a/lib/login.c b/lib/login.c
+index 9a7347f..c524108 100644
+--- a/lib/login.c
++++ b/lib/login.c
+@@ -982,21 +982,13 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 		iscsi->maxcmdsn = maxcmdsn;
+ 	}
+ 	
+-	if (size == 0) {
+-	       iscsi_set_error(iscsi, "size == 0 when parsing "
+-			       "login data");
+-	       pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+-			     pdu->private_data);
+-	       return -1;
+-	}
+-
+ 	/* XXX here we should parse the data returned in case the target
+ 	 * renegotiated some some parameters.
+ 	 *  we should also do proper handshaking if the target is not yet
+ 	 * prepared to transition to the next stage
+ 	 */
+ 
+-	do {
++	while (size > 0) {
+ 		char *end;
+ 		int len;
+ 
+@@ -1087,7 +1079,7 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 
+ 		ptr  += len + 1;
+ 		size -= len + 1;
+-	} while (size > 0);
++	}
+ 
+ 	if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
+ 		ISCSI_LOG(iscsi, 2, "target requests redirect to %s",iscsi->target_address);
diff --git a/SOURCES/libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch b/SOURCES/libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch
new file mode 100644
index 0000000..5e9e40b
--- /dev/null
+++ b/SOURCES/libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch
@@ -0,0 +1,81 @@
+From 3f8029f837ef6680e280eb700d5930c1b38dbc27 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Thu, 7 Apr 2016 13:33:14 +0200
+Subject: [PATCH 1/2] Discovery: return multiple portals for the same
+ discovered target
+
+RH-Author: Paolo Bonzini <pbonzini@redhat.com>
+Message-id: <1460035995-9887-2-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 69977
+O-Subject: [RHEL7.3 libiscsi PATCH 1/2] Discovery: return multiple portals for the same discovered target
+Bugzilla: 1266523
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Some targets return multiple TargetAddress for individual targets.
+Upstream added a list of addresses for each target, here we do not
+want to break the ABI and thus return the same target name multiple
+times.  Either way, failing the discovery is wrong.
+
+The patch is very different from upstream commit
+354f00fd4f63abec86ed0b9b64db1933936283b0, but the effect on
+the operation of iscsi-ls is the same.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ lib/discovery.c | 30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/lib/discovery.c b/lib/discovery.c
+index b5d918b..e504cf8 100644
+--- a/lib/discovery.c
++++ b/lib/discovery.c
+@@ -162,7 +162,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 			target->next = targets;
+ 			targets = target;
+ 		} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
+-			if (targets == NULL || targets->target_address != NULL) {
++			if (targets == NULL) {
+ 				iscsi_set_error(iscsi, "Invalid discovery "
+ 						"reply");
+ 				pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
+@@ -170,6 +170,34 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
+ 				iscsi_free_discovery_addresses(iscsi, targets);
+ 				return -1;
+ 			}
++			if (targets->target_address != NULL) {
++				struct iscsi_discovery_address *target;
++
++				target = iscsi_zmalloc(iscsi, sizeof(struct iscsi_discovery_address));
++				if (target == NULL) {
++					iscsi_set_error(iscsi, "Failed to allocate "
++							"data for new discovered "
++							"target");
++					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
++						      pdu->private_data);
++					iscsi_free_discovery_addresses(iscsi, targets);
++					return -1;
++				}
++				target->target_name = iscsi_strdup(iscsi, targets->target_name);
++				if (target->target_name == NULL) {
++					iscsi_set_error(iscsi, "Failed to allocate "
++							"data for new discovered "
++							"target name");
++					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
++						      pdu->private_data);
++					iscsi_free(iscsi, target);
++					target = NULL;
++					iscsi_free_discovery_addresses(iscsi, targets);
++					return -1;
++				}
++				target->next = targets;
++				targets = target;
++			}
+ 			targets->target_address = iscsi_strdup(iscsi, (char *)ptr+14);
+ 			if (targets->target_address == NULL) {
+ 				iscsi_set_error(iscsi, "Failed to allocate "
+-- 
+1.8.3.1
+
diff --git a/SOURCES/libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch b/SOURCES/libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch
new file mode 100644
index 0000000..5a9db6d
--- /dev/null
+++ b/SOURCES/libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch
@@ -0,0 +1,45 @@
+From ef6a90973cae8b047bdcbc3fcf14206efc98955a Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Thu, 7 Apr 2016 13:33:15 +0200
+Subject: [PATCH 2/2] iscsi-ls: skip link-local IPv6 addresses
+
+RH-Author: Paolo Bonzini <pbonzini@redhat.com>
+Message-id: <1460035995-9887-3-git-send-email-pbonzini@redhat.com>
+Patchwork-id: 69978
+O-Subject: [RHEL7.3 libiscsi PATCH 2/2] iscsi-ls: skip link-local IPv6 addresses
+Bugzilla: 1266523
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Thomas Huth <thuth@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Some iSCSI targets provide a link-local IPv6 address as a portal, but that
+is unusable without knowing the interface (aka scope-id) to use for the
+connection.  This causes iscsi-ls to report an EINVAL and exit.  Just
+skip the error.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit d84ee65eaad902bb41fa6bae1f8127e03cb63506)
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+---
+ src/iscsi-ls.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/iscsi-ls.c b/src/iscsi-ls.c
+index 10b0e8d..d11806c 100644
+--- a/src/iscsi-ls.c
++++ b/src/iscsi-ls.c
+@@ -156,6 +156,11 @@ void list_luns(struct client_state *clnt, const char *target, const char *portal
+ 	int full_report_size;
+ 	int i;
+ 
++	if (strncasecmp(portal, "[fe80:", 6) == 0) {
++		fprintf(stderr, "skipping link-local address\n");
++		return;
++	}
++
+ 	iscsi = iscsi_create_context(initiator);
+ 	if (iscsi == NULL) {
+ 		printf("Failed to create context\n");
+-- 
+1.8.3.1
+
diff --git a/SPECS/libiscsi.spec b/SPECS/libiscsi.spec
new file mode 100644
index 0000000..32d08dd
--- /dev/null
+++ b/SPECS/libiscsi.spec
@@ -0,0 +1,206 @@
+Name: libiscsi
+Summary: iSCSI client library
+Version: 1.9.0
+Release: 7%{?dist}
+License: LGPLv2+
+Group: System Environment/Libraries
+URL: https://github.com/sahlberg/%{name}
+
+Source: https://github.com/downloads/sahlberg/%{name}/%{name}-%{version}.tar.gz
+Patch1: 0001-do-not-reconnect-if-reconnect-is-already-defered.patch
+Patch2: 0002-fix-leak-of-iscsi_context-in-iscsi_reconnect.patch
+Patch3: 0003-Add-ASCQ-codes-related-to-thin-provisioning.patch
+Patch4: 0004-Create-safe-16-32-64-bit-accessors-for-reading-from-.patch
+Patch5: 0005-fix-bug-in-md5-code.patch
+Patch6: 0006-use-libgcrypt-for-MD5.patch
+Patch7: 0007-URL-encoded-Targetnames.patch
+Patch8: 0008-SCSI-add-a-safe-function-to-read-a-byte-from-the-dat.patch
+Patch9: 0009-scsi-lowlevel-do-not-use-unsafe-pointer-casts.patch
+Patch10: 0010-Add-a-cast-to-ssize_t.patch
+Patch11: 0011-do-not-build-test-tool.patch
+Patch12: 0012-bump-soname.patch
+Patch13: 0013-disable-ld_iscsi.patch
+Patch14: 0014-fix-another-aliasing-problem.patch
+Patch15: 0015-fix-arm-aliasing-problem.patch
+Patch16: 0016-avoid-casting-struct-sockaddr.patch
+Patch18: 0018-cleanup-rename-pdu-written.patch
+Patch19: 0019-fix-iovec-short-reads.patch
+Patch20: 0020-iscsi_reconnect-Fix-a-use-after-free.patch
+Patch21: 0021-Dont-reference-pdu-after-it-has-been-freed.patch
+Patch22: 0022-lib-Make-scsi_free_scsi_task-accept-a-NULL-task-pointer.patch
+Patch23: 0023-lib-Fix-a-memory-leak-in-scsi_cdb_persistent_reserve_out.patch
+Patch24: 0024-reconnect-do-not-initialize-iscsi-to-old_iscsi-use-old_iscsi-if-appropriate.patch
+Patch25: 0025-log-failures-typically-malloc-of-iscsi_create_context-during-reconnect.patch
+Patch26: 0026-exit-after-malloc-failure-when-allocating-sense-data-blob.patch
+Patch27: 0027-do-not-test-arrays-against-NULL.patch
+Patch28: 0028-handle-bad-iscsi--fd-in-iscsi_service.patch
+Patch29: 0029-rework-login-and-discovery-code-to-avoid-strlen-beyond-end-of-data.patch
+Patch30: 0030-check-for-a-target-being-there-before-processing-TargetAddress.patch
+Patch31: 0031-fix-CHAP-authentication.patch
+# For bz#1266523 - iscsi-ls doesn't work if target has more than one portal
+Patch32: libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch
+# For bz#1266523 - iscsi-ls doesn't work if target has more than one portal
+Patch33: libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch
+
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: libtool
+BuildRequires: popt-devel
+BuildRequires: libgcrypt-devel
+
+%description
+libiscsi is a library for attaching to iSCSI resources across
+a network.
+
+
+#######################################################################
+
+# Conflict with iscsi-initiator-utils.
+
+%global libiscsi_includedir %{_includedir}/iscsi
+%global libiscsi_libdir %{_libdir}/iscsi
+
+%prep
+%setup -q
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
+
+%build
+sh autogen.sh
+%configure --libdir=%{libiscsi_libdir}
+make %{?_smp_mflags}
+
+%install
+make DESTDIR=$RPM_BUILD_ROOT install pkgconfigdir=%{_libdir}/pkgconfig %{?_smp_mflags}
+mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d
+echo %{libiscsi_libdir} > $RPM_BUILD_ROOT/etc/ld.so.conf.d/%{name}-%{_arch}.conf
+rm $RPM_BUILD_ROOT/%{libiscsi_libdir}/libiscsi.a
+rm $RPM_BUILD_ROOT/%{libiscsi_libdir}/libiscsi.la
+
+# Remove "*.old" files
+find $RPM_BUILD_ROOT -name "*.old" -exec rm -f {} \;
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root)
+%doc COPYING LICENCE-LGPL-2.1.txt README TODO
+%{libiscsi_libdir}/libiscsi.so.*
+/etc/ld.so.conf.d/*
+
+%package utils
+Summary: iSCSI Client Utilities
+Group: Applications/System
+License: GPLv2+
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%description utils
+The libiscsi-utils package provides a set of assorted utilities to connect
+to iSCSI servers without having to set up the Linux iSCSI initiator.
+
+%files utils
+%doc COPYING LICENCE-GPL-2.txt LICENCE-LGPL-2.1.txt README TODO
+%{_bindir}/iscsi-ls
+%{_bindir}/iscsi-inq
+%{_bindir}/iscsi-readcapacity16
+
+%package devel
+Summary: iSCSI client development libraries
+Group: Development/Libraries
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%description devel
+The libiscsi-devel package includes the header files for libiscsi.
+
+%files devel
+%defattr(-,root,root)
+%doc COPYING LICENCE-LGPL-2.1.txt README TODO
+%{libiscsi_includedir}/iscsi.h
+%{libiscsi_includedir}/scsi-lowlevel.h
+%{libiscsi_libdir}/libiscsi.so
+%{_libdir}/pkgconfig/libiscsi.pc
+
+%changelog
+* Thu May 26 2016 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-7.el7
+- libiscsi-Discovery-return-multiple-portals-for-the-same-disco.patch [bz#1266523]
+- libiscsi-iscsi-ls-skip-link-local-IPv6-addresses.patch [bz#1266523]
+- Resolves: bz#1266523
+  (iscsi-ls doesn't work if target has more than one portal)
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.9.0-6
+- Mass rebuild 2014-01-24
+
+* Thu Jan 16 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-5
+- fix CHAP authentication (bz #1032358)
+- Resolves: #1032358
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.9.0-4
+- Mass rebuild 2013-12-27
+
+* Thu Nov 07 2013 Miroslav Rezanina <mrezanin@redhat.com> - 1.9.0-3
+- Fixed issues reported by coverity (bz #1026820)
+- Do not mark /etc/ld.so.conf.d/ as config (bz #1011126)
+- Resolves: #1026820 
+- Resolves: #1011126 
+
+* Tue Aug 27 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.9.0-2
+- Add missing patch 11
+- Resolves: #979953
+
+* Tue Aug 27 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.9.0-1
+- Rebase to 1.9.0
+- Cherry-pick selected patches from upstream
+- Resolves: #979953
+
+* Thu Aug 1 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-6
+- Add patch 6 to properly support escaped URIs produced by libvirt
+
+* Mon Jul 1 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-5
+- Add patch 5 to silence strict aliasing warnings
+
+* Fri May 3 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-4
+- Add patch 2 for FIPS mode
+- Add patch 3 to avoid segmentation fault on iscsi-tools
+
+* Thu Mar 7 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-3
+- Correct license for libiscsi-utils, prefer %%global to %%define
+- Add Requires
+- Remove %clean section
+
+* Fri Feb 22 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-2
+- Use %config for ld.so.conf.d file.
+
+* Fri Feb 22 2013 Paolo Bonzini <pbonzini@redhat.com> - 1.7.0-1
+- Initial version (bug 914752)