diff --git a/Makefile.in b/Makefile.in index 9d0ae34..9134801 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,6 +57,9 @@ install: lib/libiscsi.a lib/$(LIBISCSI_SO) bin/iscsi-ls bin/iscsi-inq $(INSTALLCMD) -m 644 include/iscsi.h $(exec_prefix)/include/iscsi $(INSTALLCMD) -m 644 include/scsi-lowlevel.h $(exec_prefix)/include/iscsi +iscsi-test: lib/libiscsi.a + make -C test-tool + distclean: clean rm -f config.h config.log config.status configure Makefile @@ -66,3 +69,4 @@ clean: rm -f lib/libiscsi.so* rm -f lib/libiscsi.a rm -f iscsi-inq iscsi-ls + make -C test-tool clean diff --git a/test-tool/0100_read10_simple.c b/test-tool/0100_read10_simple.c new file mode 100644 index 0000000..09abb0e --- /dev/null +++ b/test-tool/0100_read10_simple.c @@ -0,0 +1,113 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0100_read10_simple(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + uint32_t block_size, num_blocks; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + ret = 0; + + /* read the first 1 - 256 blocks at the start of the LUN */ + printf("Reading first 1-256 blocks ... "); + for (i=1; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, 0, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + + /* read the last 1 - 256 blocks at the end of the LUN */ + printf("Reading last 1-256 blocks ... "); + for (i=1; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, num_blocks +1 - i, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0101_read10_beyond_eol.c b/test-tool/0101_read10_beyond_eol.c new file mode 100644 index 0000000..8953290 --- /dev/null +++ b/test-tool/0101_read10_beyond_eol.c @@ -0,0 +1,141 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0101_read10_beyond_eol(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + uint32_t block_size, num_blocks; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + ret = 0; + + /* read 1-256 blocks, one block beyond the end-of-lun */ + printf("Reading last 1-256 blocks one block beyond eol ... "); + for (i=1; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, num_blocks + 2 - i, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status == SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not fail with sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + if (task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not return sense key ILLEGAL_REQUEST.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + if (task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not return sense ascq LBA OUT OF RANGE.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + + /* read 2-256 blocks, all but one block beyond the eol */ + printf("Reading 1-255 blocks beyond eol starting at last block ... "); + for (i=2; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, num_blocks, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status == SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not return sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + if (task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not return sense key ILLEGAL_REQUEST.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + if (task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) { + printf("[FAILED]\n"); + printf("Read10 beyond end-of-lun did not return sense ascq LBA OUT OF RANGE.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0102_read10_0blocks.c b/test-tool/0102_read10_0blocks.c new file mode 100644 index 0000000..425e63e --- /dev/null +++ b/test-tool/0102_read10_0blocks.c @@ -0,0 +1,148 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0102_read10_0blocks(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + uint32_t block_size, num_blocks; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + ret = 0; + + /* read10 0 blocks one block at lba 0 */ + printf("Reading 0 blocks at lba:0 ... "); + task = iscsi_read10_sync(iscsi, lun, 0, 0, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 0 at lba:0 failed with sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + /* read10 0 blocks one block beyond the eol */ + printf("Reading 0 blocks at one block beyond end ... "); + task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 0 one block beyond end-of-lun failed with sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* read10 0 blocks two blocks beyond the eol */ + printf("Reading 0 blocks at two blocks beyond end ... "); + task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 0 two blocks beyond end-of-lun failed with sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* read10 0 at lba -1 */ + printf("Reading 0 blocks at lba:-1 ... "); + task = iscsi_read10_sync(iscsi, lun, 0xffffff, 0, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 0 at lba:-1 failed with sense.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0103_read10_rdprotect.c b/test-tool/0103_read10_rdprotect.c new file mode 100644 index 0000000..04d55ae --- /dev/null +++ b/test-tool/0103_read10_rdprotect.c @@ -0,0 +1,118 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0103_read10_rdprotect(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + int full_size; + struct scsi_inquiry_standard *inq; + int ret, i, lun; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* See how big this inquiry data is */ + task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64); + if (task == NULL || task->status != SCSI_STATUS_GOOD) { + printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi)); + return -1; + } + full_size = scsi_datain_getfullsize(task); + if (full_size > task->datain.size) { + scsi_free_scsi_task(task); + + /* we need more data for the full list */ + if ((task = iscsi_inquiry_sync(iscsi, lun, 0, 0, full_size)) == NULL) { + printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi)); + return -1; + } + } + + inq = scsi_datain_unmarshall(task); + if (inq == NULL) { + printf("failed to unmarshall inquiry datain blob\n"); + scsi_free_scsi_task(task); + return -1; + } + + if (inq->protect) { + printf("LUN is formatted with protection information. Skipping test\n"); + scsi_free_scsi_task(task); + return -1; + } + + scsi_free_scsi_task(task); + + + ret = 0; + + /* Try out Different non-zero values for RDPROTECT. They should all fail */ + printf("Read10 with non-zero RDPROTECT ... "); + for (i = 1; i < 8; i++) { + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = (i<<5)&0xe0; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + if (task->status != SCSI_STATUS_CHECK_CONDITION + || task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST + || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { + printf("[FAILED]\n"); + printf("Read10 with rdprotect should fail with ILLEGAL REQUEST/INVALID OPCODE\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0104_read10_flags.c b/test-tool/0104_read10_flags.c new file mode 100644 index 0000000..e0c0ee2 --- /dev/null +++ b/test-tool/0104_read10_flags.c @@ -0,0 +1,226 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0104_read10_flags(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + int ret, lun; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + + ret = 0; + + /* Try out DPO : 1 */ + printf("Read10 with DPO==1 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = 0x10; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 with DPO==1 Failed. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + + /* Try out FUA : 1 FUA_NV : 0 */ + printf("Read10 with FUA==1 FUA_NV==0 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = 0x08; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 with FUA==1 FUA_NV==0 Failed. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* Try out FUA : 1 FUA_NV : 1 */ + printf("Read10 with FUA==1 FUA_NV==1 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = 0x0a; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 with FUA==1 FUA_NV==1 Failed. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* Try out FUA : 0 FUA_NV : 1 */ + printf("Read10 with FUA==0 FUA_NV==1 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = 0x02; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 with FUA==0 FUA_NV==1 Failed. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* Try out DPO : 1 FUA : 1 FUA_NV : 1 */ + printf("Read10 with DPO==1 FUA==1 FUA_NV==1 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[1] = 0x18; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 512; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 with DPO==1 FUA==1 FUA_NV==0Failed. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0105_read10_invalid.c b/test-tool/0105_read10_invalid.c new file mode 100644 index 0000000..47ee019 --- /dev/null +++ b/test-tool/0105_read10_invalid.c @@ -0,0 +1,119 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0105_read10_invalid(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct iscsi_data data; + char buf[512]; + int ret, lun; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + + ret = 0; + + /* Try a read of 1 block but xferlength == 0 */ + printf("Read10 1 block but with iscsi ExpectedDataTransferLength==0 ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_READ; + task->expxferlen = 0; + + if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status == SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==0 should fail.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* Try a read of 1 block but make it a data-out write on the iscsi layer */ + printf("Read10 of 1 block but sent as data-out write in iscsi layer ... "); + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + printf("Failed to allocate task structure\n"); + ret = -1; + goto finished; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_READ10; + task->cdb[8] = 1; + task->cdb_size = 10; + task->xfer_dir = SCSI_XFER_WRITE; + task->expxferlen = sizeof(buf); + + data.size = sizeof(buf); + data.data = &buf[0]; + + if (iscsi_scsi_command_sync(iscsi, lun, task, &data) == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + + goto finished; + } + if (task->status == SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 of 1 block but iscsi data-out write should fail.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0110_readcapacity10_simple.c b/test-tool/0110_readcapacity10_simple.c new file mode 100644 index 0000000..bea7cd3 --- /dev/null +++ b/test-tool/0110_readcapacity10_simple.c @@ -0,0 +1,68 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0110_readcapacity10_simple(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + + ret = 0; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + printf("Test that Readcapacity10 is supported ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("[FAILED]\n"); + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0111_readcapacity10_pmi.c b/test-tool/0111_readcapacity10_pmi.c new file mode 100644 index 0000000..ff200ad --- /dev/null +++ b/test-tool/0111_readcapacity10_pmi.c @@ -0,0 +1,182 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0111_readcapacity10_pmi(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + int ret, lun; + struct scsi_readcapacity10 *rc10; + uint32_t block_size, num_blocks; + + ret = 0; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + /* lba != 0 and pmi == 0 is an error */ + printf("Readcapacity10 PMI==0 LBA!=0 ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, 10, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_CHECK_CONDITION + || task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST + || task->sense.ascq !=SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB ) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==0 and LBA!=0 should fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* PMI==1 LBA==0 */ + printf("Readcapacity10 PMI==1 LBA==0 ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 1); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==1 and LBA==0 should not fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + /* PMI==1 LBA==EOL-1 */ + printf("Readcapacity10 PMI==1 LBA==EOL-1 ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, num_blocks-1, 1); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==1 and LBA==EOL-1 should not fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + /* PMI==1 LBA==EOL */ + printf("Readcapacity10 PMI==1 LBA==EOL ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, num_blocks, 1); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==1 and LBA==EOL should not fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + + /* PMI==1 LBA==EOL+1 */ + printf("Readcapacity10 PMI==1 LBA==EOL+1 ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, num_blocks+1, 1); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==1 and LBA==EOL+1 should not fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + /* PMI==1 LBA==-1 */ + printf("Readcapacity10 PMI==1 LBA==-1 ... "); + task = iscsi_readcapacity10_sync(iscsi, lun, 0xffffffff, 1); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Readcapacity10 PMI==1 and LBA==-1 should not fail with sense code.\n"); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0120_read6_simple.c b/test-tool/0120_read6_simple.c new file mode 100644 index 0000000..14c93da --- /dev/null +++ b/test-tool/0120_read6_simple.c @@ -0,0 +1,90 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0120_read6_simple(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + uint32_t block_size, num_blocks; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + ret = 0; + + /* read the first 1 - 256 blocks at the start of the LUN */ + printf("Reading first 1-256 blocks ... "); + for (i = 1; i <= 256; i++) { + task = iscsi_read6_sync(iscsi, lun, 0, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read6 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read6 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/0120_read6_simple.c~ b/test-tool/0120_read6_simple.c~ new file mode 100644 index 0000000..09abb0e --- /dev/null +++ b/test-tool/0120_read6_simple.c~ @@ -0,0 +1,113 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test.h" + +int T0100_read10_simple(const char *initiator, const char *url) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity10 *rc10; + int ret, i, lun; + uint32_t block_size, num_blocks; + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0); + if (task == NULL) { + printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc10 = scsi_datain_unmarshall(task); + if (rc10 == NULL) { + printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc10->block_size; + num_blocks = rc10->lba; + scsi_free_scsi_task(task); + + + + ret = 0; + + /* read the first 1 - 256 blocks at the start of the LUN */ + printf("Reading first 1-256 blocks ... "); + for (i=1; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, 0, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + + /* read the last 1 - 256 blocks at the end of the LUN */ + printf("Reading last 1-256 blocks ... "); + for (i=1; i<=256; i++) { + task = iscsi_read10_sync(iscsi, lun, num_blocks +1 - i, i * block_size, block_size); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("Read10 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/Makefile b/test-tool/Makefile new file mode 100644 index 0000000..f728050 --- /dev/null +++ b/test-tool/Makefile @@ -0,0 +1,16 @@ +LIBS=-lpopt +CC=gcc +CFLAGS=-g -O0 -fPIC -Wall -W -I. -I./include -I../include "-D_U_=__attribute__((unused))" +TESTS=0100_read10_simple.o 0101_read10_beyond_eol.o 0102_read10_0blocks.o \ +0103_read10_rdprotect.o 0104_read10_flags.o 0105_read10_invalid.o \ +0110_readcapacity10_simple.o 0111_readcapacity10_pmi.o \ +0120_read6_simple.o + +all: iscsi-test + +iscsi-test: iscsi-test.c $(TESTS) + $(CC) $(CFLAGS) iscsi-test.c -o iscsi-test $(TESTS) ../lib/libiscsi.a $(LIBS) + +clean: + rm -f *.o + rm iscsi-test \ No newline at end of file diff --git a/test-tool/iscsi-test.c b/test-tool/iscsi-test.c new file mode 100644 index 0000000..94540a0 --- /dev/null +++ b/test-tool/iscsi-test.c @@ -0,0 +1,207 @@ +/* + iscsi-test tool + + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi.h" +#include "iscsi-test.h" + +char *initiator = "iqn.2010-11.iscsi-test"; + +struct scsi_test { + char *name; + int (*test)(const char *initiator, const char *url); +}; + +struct scsi_test tests[] = { +/* read10*/ +{ "T0100_read10_simple", T0100_read10_simple }, +{ "T0101_read10_beyond_eol", T0101_read10_beyond_eol }, +{ "T0102_read10_0blocks", T0102_read10_0blocks }, +{ "T0103_read10_rdprotect", T0103_read10_rdprotect }, +{ "T0104_read10_flags", T0104_read10_flags }, +{ "T0105_read10_invalid", T0105_read10_invalid }, + +/* readcapacity10*/ +{ "T0110_readcapacity10_simple", T0110_readcapacity10_simple }, +{ "T0111_readcapacity10_pmi", T0111_readcapacity10_pmi }, + +/* read6*/ +{ "T0120_read6_simple", T0120_read6_simple }, + +{ NULL, NULL } +}; + +void print_usage(void) +{ + fprintf(stderr, "Usage: iscsi-inq [-?] [-?|--help] [--usage] [-i|--initiator-name=iqn-name]\n" + "\t\t\n"); +} + +void print_help(void) +{ + fprintf(stderr, "Usage: iscsi-inq [OPTION...] \n"); + fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n"); + fprintf(stderr, " -t, --test=test-name Which test to run. Default is to run all tests.\n"); + fprintf(stderr, " -l, --list List all tests.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Help options:\n"); + fprintf(stderr, " -?, --help Show this help message\n"); + fprintf(stderr, " --usage Display brief usage message\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "iSCSI URL format : %s\n", ISCSI_URL_SYNTAX); + fprintf(stderr, "\n"); + fprintf(stderr, " is either of:\n"); + fprintf(stderr, " \"hostname\" iscsi.example\n"); + fprintf(stderr, " \"ipv4-address\" 10.1.1.27\n"); + fprintf(stderr, " \"ipv6-address\" [fce0::1]\n"); +} + + +struct iscsi_context *iscsi_context_login(const char *initiatorname, const char *url, int *lun) +{ + struct iscsi_context *iscsi; + struct iscsi_url *iscsi_url; + + iscsi = iscsi_create_context(initiatorname); + if (iscsi == NULL) { + fprintf(stderr, "Failed to create context\n"); + return NULL; + } + + iscsi_url = iscsi_parse_full_url(iscsi, url); + if (iscsi_url == NULL) { + fprintf(stderr, "Failed to parse URL: %s\n", + iscsi_get_error(iscsi)); + iscsi_destroy_context(iscsi); + return NULL; + } + + iscsi_set_targetname(iscsi, iscsi_url->target); + 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_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd) != 0) { + fprintf(stderr, "Failed to set initiator username and password\n"); + iscsi_destroy_url(iscsi_url); + iscsi_destroy_context(iscsi); + return NULL; + } + } + + if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) { + fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(iscsi)); + iscsi_destroy_url(iscsi_url); + iscsi_destroy_context(iscsi); + return NULL; + } + if (lun != NULL) { + *lun = iscsi_url->lun; + } + + iscsi_destroy_url(iscsi_url); + return iscsi; +} + + +int main(int argc, const char *argv[]) +{ + poptContext pc; + const char **extra_argv; + int extra_argc = 0; + const char *url = NULL; + int show_help = 0, show_usage = 0, list_tests = 0; + int res; + struct scsi_test *test; + char *testname = NULL; + + struct poptOption popt_options[] = { + { "help", '?', POPT_ARG_NONE, &show_help, 0, "Show this help message", NULL }, + { "usage", 0, POPT_ARG_NONE, &show_usage, 0, "Display brief usage message", NULL }, + { "list", 'l', POPT_ARG_NONE, &list_tests, 0, "List all tests", NULL }, + { "initiator-name", 'i', POPT_ARG_STRING, &initiator, 0, "Initiatorname to use", "iqn-name" }, + { "test", 't', POPT_ARG_STRING, &testname, 0, "Which test to run", "testname" }, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_POSIXMEHARDER); + if ((res = poptGetNextOpt(pc)) < -1) { + fprintf(stderr, "Failed to parse option : %s %s\n", + poptBadOption(pc, 0), poptStrerror(res)); + exit(10); + } + extra_argv = poptGetArgs(pc); + if (extra_argv) { + url = *extra_argv; + extra_argv++; + while (extra_argv[extra_argc]) { + extra_argc++; + } + } + + if (show_help != 0) { + print_help(); + exit(0); + } + + if (show_usage != 0) { + print_usage(); + exit(0); + } + + if (list_tests != 0) { + for (test = &tests[0]; test->name; test++) { + printf("%s\n", test->name); + } + exit(0); + } + poptFreeContext(pc); + + if (url == NULL) { + fprintf(stderr, "You must specify the URL\n"); + print_usage(); + exit(10); + } + + for (test = &tests[0]; test->name; test++) { + if (testname != NULL && strcmp(testname, test->name)) { + continue; + } + + printf("=========\n"); + printf("Running test %s\n", test->name); + res = test->test(initiator, url); + if (res == 0) { + printf("TEST %s [OK]\n", test->name); + } else { + printf("TEST %s [FAILED]\n", test->name); + } + printf("\n"); + } + + return 0; +} + diff --git a/test-tool/iscsi-test.h b/test-tool/iscsi-test.h new file mode 100644 index 0000000..7253437 --- /dev/null +++ b/test-tool/iscsi-test.h @@ -0,0 +1,33 @@ +/* + iscsi-test tool + + Copyright (C) 2010 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +struct iscsi_context *iscsi_context_login(const char *initiatorname, const char *url, int *lun); + + +int T0100_read10_simple(const char *initiator, const char *url); +int T0101_read10_beyond_eol(const char *initiator, const char *url); +int T0102_read10_0blocks(const char *initiator, const char *url); +int T0103_read10_rdprotect(const char *initiator, const char *url); +int T0104_read10_flags(const char *initiator, const char *url); +int T0105_read10_invalid(const char *initiator, const char *url); + +int T0110_readcapacity10_simple(const char *initiator, const char *url); +int T0111_readcapacity10_pmi(const char *initiator, const char *url); + +int T0120_read6_simple(const char *initiator, const char *url);