Rebased to version 1.11.0

- Most patches removed
- New tool iscsi-swp + manpages
This commit is contained in:
Paolo Bonzini 2014-06-12 14:23:43 +02:00
parent 37e667cddf
commit ca14f38d38
24 changed files with 74 additions and 2474 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/libiscsi-1.9.0.tar.gz
/libiscsi-1.11.0.tar.gz

View File

@ -1,13 +0,0 @@
diff --git a/Makefile.am b/Makefile.am
index b750cdb..8bde4ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,7 +52,7 @@ bin_iscsi_dd_SOURCES = examples/iscsi-dd.c
# libiscsi test tool
-noinst_PROGRAMS += bin/iscsi-test
+bin_PROGRAMS += bin/iscsi-test
dist_noinst_HEADERS += test-tool/iscsi-support.h \
test-tool/iscsi-test.h \
test-tool/iscsi-test-cu.h

View File

@ -1,34 +0,0 @@
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: [PATCH] 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>
---
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

View File

@ -1,29 +0,0 @@
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: [PATCH] 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>
---
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

View File

@ -1,75 +0,0 @@
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: [PATCH] Add ASCQ codes related to thin-provisioning
Signed-off-by: Peter Lieven <pl@kamp.de>
---
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

View File

@ -1,385 +0,0 @@
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: [PATCH] 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.
---
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

View File

@ -1,25 +0,0 @@
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: [PATCH] fix bug in md5 code
---
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

View File

@ -1,162 +0,0 @@
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: [PATCH] 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>
---
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

View File

@ -1,228 +0,0 @@
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: [PATCH] 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
---
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

View File

@ -1,537 +0,0 @@
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: [PATCH] SCSI: add a safe function to read a byte from the datain
buffer and use it throughout the unmarshalling code
---
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

View File

@ -1,113 +0,0 @@
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: [PATCH] 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>
---
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

View File

@ -1,25 +0,0 @@
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: [PATCH] Add a cast to ssize_t
---
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

View File

@ -1,26 +0,0 @@
From dcb223badcf36e7dd6b826fa41c3ee24fe0e6a4b Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Date: Sat, 29 Jun 2013 12:23:55 -0700
Subject: [PATCH] Use PRIu64 for format string
---
test-tool/iscsi-support.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c
index e61b97c..0f3e2e8 100644
--- a/test-tool/iscsi-support.c
+++ b/test-tool/iscsi-support.c
@@ -917,7 +917,8 @@ prin_verify_reserved_as(struct iscsi_context *iscsi, int lun,
}
if (rr->reservation_key != key) {
logging(LOG_NORMAL,
- "[FAILED] Failed to find reservation key 0x%llx: found 0x%lx.",
+ "[FAILED] Failed to find reservation key 0x%llx: found 0x%"
+ PRIu64 ".",
key, rr->reservation_key);
ret = -1;
goto dun;
--
1.8.1.4

View File

@ -1,15 +1,16 @@
ABI was not preserved between 1.7.0 and 1.9.0.
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
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 66c02dd..828001a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -10,9 +10,9 @@ if !HAVE_LIBGCRYPT
libiscsi_la_SOURCES += 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 \
-SOCURRENT=3
+SOCURRENT=4
SOREVISON=11
-SOAGE=1
+SOAGE=0
libiscsi_la_LDFLAGS = \
-version-info $(SOCURRENT):$(SOREVISON):$(SOAGE) -bindir $(bindir) \
-no-undefined -export-symbols libiscsi.syms

View File

@ -1,13 +1,13 @@
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 $@ $^
diff --git a/configure.ac b/configure.ac
index e1d01c6..72a5019 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ LT_INIT
# 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
AC_CANONICAL_HOST
AM_CONDITIONAL(LD_ISCSI,
- [expr "$host_os" : linux > /dev/null 2>&1])
+ [false])
AM_PROG_CC_C_O
enable_write_strings="yes"

View File

@ -1,18 +0,0 @@
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

View File

@ -1,212 +0,0 @@
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);
^
Based on this patch:
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: [PATCH] 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
---
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/Makefile.am b/Makefile.am
index 1a76d12..b0d5224 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -152,7 +152,6 @@ bin_iscsi_test_SOURCES = test-tool/iscsi-test.c \
test-tool/0422_reserve6_logout.c \
test-tool/0423_reserve6_sessionloss.c \
test-tool/0424_reserve6_target_reset.c \
- test-tool/0430_report_all_supported_ops.c \
\
test-tool/1000_cmdsn_invalid.c \
test-tool/1010_datasn_invalid.c \
diff --git a/test-tool/iscsi-test.c b/test-tool/iscsi-test.c
index 1e6bcfa..3250b56 100644
--- a/test-tool/iscsi-test.c
+++ b/test-tool/iscsi-test.c
@@ -230,9 +230,6 @@ static struct scsi_test tests[] = {
{ "T0423_reserve6_sessionloss", T0423_reserve6_sessionloss },
{ "T0424_reserve6_target_reset", T0424_reserve6_target_reset },
-/* Maintenance In - Report Supported Operations */
-{ "T0430_report_all_supported_ops", T0430_report_all_supported_ops },
-
/* iSCSI protocol tests */
/* invalid cmdsn from initiator */
diff --git a/test-tool/iscsi-test.h b/test-tool/iscsi-test.h
index d214fda..bb179ee 100644
--- a/test-tool/iscsi-test.h
+++ b/test-tool/iscsi-test.h
@@ -173,8 +173,6 @@ int T0422_reserve6_logout(const char *initiator, const char *url);
int T0423_reserve6_sessionloss(const char *initiator, const char *url);
int T0424_reserve6_target_reset(const char *initiator, const char *url);
-int T0430_report_all_supported_ops(const char *initiator, const char *url);
-
int T1000_cmdsn_invalid(const char *initiator, const char *url);
int T1010_datasn_invalid(const char *initiator, const char *url);
int T1020_bufferoffset_invalid(const char *initiator, const char *url);

View File

@ -1,76 +0,0 @@
From 4874e24d0e5ea1f930e8d8ea60a1df78f2cc814c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 2 Aug 2013 14:19:29 +0200
Subject: [PATCH] avoid casting struct sockaddr
On ARM, this produces a warning. Use a union instead.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
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

View File

@ -1,209 +0,0 @@
From d901509bcbecc912ce79087915cae355d75ca03c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 2 Aug 2013 16:24:34 +0200
Subject: [PATCH] use scsi_get/set_uint16/32/64 in tests
Fixes ARM problems too.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/libiscsi.syms | 6 ++++++
test-tool/1000_cmdsn_invalid.c | 4 ++--
test-tool/1010_datasn_invalid.c | 10 +++++-----
test-tool/1020_bufferoffset_invalid.c | 6 +++---
test-tool/1031_unsolicited_data_out.c | 7 +++----
test-tool/1041_unsolicited_immediate_data.c | 2 +-
test-tool/1042_unsolicited_nonimmediate_data.c | 4 ++--
test-tool/1100_persistent_reserve_in_read_keys_simple.c | 2 +-
test-tool/test_prin_read_keys_simple.c | 2 +-
9 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms
index f0ca8cd..e887506 100644
--- a/lib/libiscsi.syms
+++ b/lib/libiscsi.syms
@@ -202,6 +202,9 @@ scsi_devqualifier_to_str
scsi_devtype_to_str
scsi_free_scsi_task
scsi_get_task_private_ptr
+scsi_get_uint16
+scsi_get_uint32
+scsi_get_uint64
scsi_inquiry_pagecode_to_str
scsi_protocol_identifier_to_str
scsi_reportluns_cdb
@@ -211,6 +214,9 @@ scsi_sense_ascq_str
scsi_pr_type_str
scsi_sense_key_str
scsi_set_task_private_ptr
+scsi_set_uint16
+scsi_set_uint32
+scsi_set_uint64
scsi_task_add_data_in_buffer
scsi_task_add_data_out_buffer
scsi_task_set_iov_in
diff --git a/test-tool/1000_cmdsn_invalid.c b/test-tool/1000_cmdsn_invalid.c
index 3c88d2c..5b50a56 100644
--- a/test-tool/1000_cmdsn_invalid.c
+++ b/test-tool/1000_cmdsn_invalid.c
@@ -29,11 +29,11 @@ static int my_iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
switch (change_cmdsn) {
case 1:
/* change the cmdsn so it becomes too big */
- *(uint32_t *)&pdu->outdata.data[24] = htonl(iscsi->maxcmdsn + 1);
+ scsi_set_uint32(&pdu->outdata.data[24], iscsi->maxcmdsn + 1);
break;
case 2:
/* change the cmdsn so it becomes too small */
- *(uint32_t *)&pdu->outdata.data[24] = 0;
+ scsi_set_uint32(&pdu->outdata.data[24], 0);
break;
}
diff --git a/test-tool/1010_datasn_invalid.c b/test-tool/1010_datasn_invalid.c
index f605354..e9e027d 100644
--- a/test-tool/1010_datasn_invalid.c
+++ b/test-tool/1010_datasn_invalid.c
@@ -34,20 +34,20 @@ static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu
switch (clamp_datasn) {
case 1:
/* change datasn to 0 */
- *(uint32_t *)&pdu->outdata.data[36] = 0;
+ scsi_set_uint32(&pdu->outdata.data[36], 0);
break;
case 2:
/* change datasn to 27 */
- *(uint32_t *)&pdu->outdata.data[36] = htonl(27);
+ scsi_set_uint32(&pdu->outdata.data[36], 27);
break;
case 3:
/* change datasn to -1 */
- *(uint32_t *)&pdu->outdata.data[36] = htonl(-1);
+ scsi_set_uint32(&pdu->outdata.data[36], -1);
break;
case 4:
/* change datasn from (0,1) to (1,0) */
- datasn = ntohl(*(uint32_t *)&pdu->outdata.data[36]);
- *(uint32_t *)&pdu->outdata.data[36] = htonl(1 - datasn);
+ datasn = scsi_get_uint32(&pdu->outdata.data[36]);
+ scsi_set_uint32(&pdu->outdata.data[36], 1 - datasn);
break;
}
return 0;
diff --git a/test-tool/1020_bufferoffset_invalid.c b/test-tool/1020_bufferoffset_invalid.c
index c044094..6260dec 100644
--- a/test-tool/1020_bufferoffset_invalid.c
+++ b/test-tool/1020_bufferoffset_invalid.c
@@ -31,15 +31,15 @@ static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu
if (pdu->outdata.data[0] != ISCSI_PDU_DATA_OUT) {
return 0;
}
- buffer_offset = ntohl(*(uint32_t *)&pdu->outdata.data[40]);
+ buffer_offset = scsi_get_uint32(&pdu->outdata.data[40]);
switch (change_bufferoffset) {
case 1:
/* Add 1M to the buffer offset */
- *(uint32_t *)&pdu->outdata.data[40] = htonl(buffer_offset + 1024*1024);
+ scsi_set_uint32(&pdu->outdata.data[40], buffer_offset + 1024*1024);
break;
case 2:
/* Add -'block_size' to the buffer offset */
- *(uint32_t *)&pdu->outdata.data[40] = htonl(buffer_offset - block_size);
+ scsi_set_uint32(&pdu->outdata.data[40], buffer_offset - block_size);
break;
}
return 0;
diff --git a/test-tool/1031_unsolicited_data_out.c b/test-tool/1031_unsolicited_data_out.c
index fca38c8..39a1ff9 100644
--- a/test-tool/1031_unsolicited_data_out.c
+++ b/test-tool/1031_unsolicited_data_out.c
@@ -74,8 +74,7 @@ my_iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
}
/* update data segment length */
- *(uint32_t *)&pdu->outdata.data[4] = htonl(pdu->outdata.size
- - ISCSI_HEADER_SIZE);
+ scsi_set_uint32(&pdu->outdata.data[4], pdu->outdata.size - ISCSI_HEADER_SIZE);
return 0;
}
@@ -83,13 +82,13 @@ my_iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
static void
my_iscsi_pdu_set_itt(struct iscsi_pdu *pdu, uint32_t itt)
{
- *(uint32_t *)&pdu->outdata.data[16] = htonl(itt);
+ scsi_set_uint32(&pdu->outdata.data[16], itt);
}
static void
my_iscsi_pdu_set_expstatsn(struct iscsi_pdu *pdu, uint32_t expstatsnsn)
{
- *(uint32_t *)&pdu->outdata.data[28] = htonl(expstatsnsn);
+ scsi_set_uint32(&pdu->outdata.data[28], expstatsnsn);
}
static void
diff --git a/test-tool/1041_unsolicited_immediate_data.c b/test-tool/1041_unsolicited_immediate_data.c
index 3bb4d28..2959236 100644
--- a/test-tool/1041_unsolicited_immediate_data.c
+++ b/test-tool/1041_unsolicited_immediate_data.c
@@ -37,7 +37,7 @@ static int my_queue_immediate_data(struct iscsi_context *iscsi _U_, struct iscsi
pdu_was_valid = 0;
return 0;
}
- if ( (*(uint32_t *)&pdu->outdata.data[4] & 0x00ffffff) != htonl(block_size)) {
+ if ( (scsi_get_uint32(&pdu->outdata.data[4]) & 0x00ffffff) != block_size) {
printf("SCSI-Command PDU did not have one block of immediate data.\n");
pdu_was_valid = 0;
return 0;
diff --git a/test-tool/1042_unsolicited_nonimmediate_data.c b/test-tool/1042_unsolicited_nonimmediate_data.c
index bb2112b..ec36c41 100644
--- a/test-tool/1042_unsolicited_nonimmediate_data.c
+++ b/test-tool/1042_unsolicited_nonimmediate_data.c
@@ -37,7 +37,7 @@ static int my_queue_immediate_data(struct iscsi_context *iscsi _U_, struct iscsi
pdu_was_valid = 0;
return 0;
}
- if ( *(uint32_t *)&pdu->outdata.data[4] & 0x00ffffff ) {
+ if ( scsi_get_uint32(&pdu->outdata.data[4]) & 0x00ffffff ) {
printf("SCSI-Command PDU had non-zero datasegmentsize.\n");
pdu_was_valid = 0;
return 0;
@@ -50,7 +50,7 @@ static int my_queue_immediate_data(struct iscsi_context *iscsi _U_, struct iscsi
pdu_was_valid = 0;
return 0;
}
- if ( (*(uint32_t *)&pdu->outdata.data[4] & 0x00ffffff) != htonl(block_size)) {
+ if ( (scsi_get_uint32(&pdu->outdata.data[4]) & 0x00ffffff) != block_size) {
printf("The DATA-OUT PDU did not carry a full block.\n");
pdu_was_valid = 0;
return 0;
diff --git a/test-tool/1100_persistent_reserve_in_read_keys_simple.c b/test-tool/1100_persistent_reserve_in_read_keys_simple.c
index 24de2ff..86bb83b 100644
--- a/test-tool/1100_persistent_reserve_in_read_keys_simple.c
+++ b/test-tool/1100_persistent_reserve_in_read_keys_simple.c
@@ -90,7 +90,7 @@ int T1100_persistent_reserve_in_read_keys_simple(const char *initiator, const ch
/* Verify that ADDITIONAL_LENGTH matches DATA-IN size */
printf("Verify that ADDITIONAL_LENGTH matches DATA-IN size ... ");
- al = ntohl(*(uint32_t *)&task->datain.data[4]);
+ al = scsi_get_uint32(&task->datain.data[4]);
if (al != task->datain.size - 8) {
printf("[FAILED]\n");
printf("ADDITIONAL_LENGTH was %d bytes but %d was expected.\n",
diff --git a/test-tool/test_prin_read_keys_simple.c b/test-tool/test_prin_read_keys_simple.c
index ba7b81e..0cf6edc 100644
--- a/test-tool/test_prin_read_keys_simple.c
+++ b/test-tool/test_prin_read_keys_simple.c
@@ -47,7 +47,7 @@ test_prin_read_keys_simple(void)
}
logging(LOG_VERBOSE, "Test ADDITIONAL_LENGTH matches DATA_IN size.");
- al = ntohl(*(uint32_t *)&task->datain.data[4]);
+ al = scsi_get_uint32(&task->datain.data[4]);
if (al != task->datain.size - 8) {
logging(LOG_NORMAL,
"[FAILED] ADDITIONAL_LENGTH was %d bytes but %d was expected.",
--
1.8.1.4

View File

@ -1,89 +0,0 @@
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: [PATCH] Cleanup: rename pdu->written -> pdu->outdata_written
---
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

View File

@ -1,153 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Subject: [PATCH] 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>
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);
}

31
0020-reconnect-fix.patch Normal file
View File

@ -0,0 +1,31 @@
From fd5471960f8f0556efae2c9539867fb3c1ca0882 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 2 Apr 2014 12:44:04 +0200
Subject: [PATCH] libiscsi: fix dangling pointer for outqueue_current
The outqueue_current PDU might also be in waitpdu if it does not have
ISCSI_PDU_DELETE_WHEN_SENT. Because outqueue_current is freed after
the waitpdu list, we need to ensure it is kept up to date when a PDU
is freed. This can happen in many places (reconnect, defer_reconnect,
cancel) so just do it in iscsi_free_pdu.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
lib/pdu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/pdu.c b/lib/pdu.c
index 89b15c2..4db5f27 100644
--- a/lib/pdu.c
+++ b/lib/pdu.c
@@ -147,6 +147,10 @@ iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
}
pdu->indata.data = NULL;
+ if (iscsi->outqueue_current == pdu) {
+ iscsi->outqueue_current = NULL;
+ }
+
iscsi_sfree(iscsi, pdu);
}

View File

@ -1,32 +1,15 @@
Name: libiscsi
Summary: iSCSI client library
Version: 1.9.0
Release: 6%{?dist}
Version: 1.11.0
Release: 1%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
URL: https://github.com/sahlberg/%{name}
Source: https://github.com/downloads/sahlberg/%{name}/%{name}-%{version}.tar.gz
Patch0: 0000-install-iscsi-test.patch
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-Use-PRIu64-for-format-string.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
Patch17: 0017-use-scsi_get-set_uint16-32-64-in-tests.patch
Patch18: 0018-cleanup-rename-pdu-written.patch
Patch19: 0019-fix-iovec-short-reads.patch
Patch20: 0020-reconnect-fix.patch
BuildRequires: autoconf
BuildRequires: automake
@ -49,26 +32,9 @@ a network.
%prep
%setup -q
%patch0 -p1
%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
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%build
sh autogen.sh
@ -110,7 +76,12 @@ to iSCSI servers without having to set up the Linux iSCSI initiator.
%{_bindir}/iscsi-ls
%{_bindir}/iscsi-inq
%{_bindir}/iscsi-readcapacity16
%{_bindir}/iscsi-test
%{_bindir}/iscsi-swp
%{_bindir}/iscsi-test-cu
%{_mandir}/man1/iscsi-ls.1.gz
%{_mandir}/man1/iscsi-inq.1.gz
%{_mandir}/man1/iscsi-swp.1.gz
%{_mandir}/man1/iscsi-test-cu.1.gz
%package devel
Summary: iSCSI client development libraries
@ -129,6 +100,11 @@ The libiscsi-devel package includes the header files for libiscsi.
%{_libdir}/pkgconfig/libiscsi.pc
%changelog
* Thu Jun 12 2014 Paolo Bonzini <pbonzini@redhat.com> - 1.11.0-1
- Rebased to version 1.11.0
- Most patches removed
- New tool iscsi-swp + manpages
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.9.0-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild

View File

@ -1 +1 @@
827a76e958815faf199078052791d8c4 libiscsi-1.9.0.tar.gz
a2a9ab4800e86f448a819ac950ece80c libiscsi-1.11.0.tar.gz