Import the distribution files for the iSCSI target, developed from the

original Intel code (BSD-licensed) in othersrc, by myself.

This provides an iSCSI target implementation in userland, as well as a
test harness which also runs in userland.

The iSCSI target has been tested with version 1.06 of the Microsoft
initiator, as well as with its own test harness.
This commit is contained in:
agc 2006-02-08 18:56:14 +00:00
parent 238f1027f9
commit 33645f4ad2
72 changed files with 28928 additions and 0 deletions

198
dist/iscsi/doc/FAQ vendored Normal file
View File

@ -0,0 +1,198 @@
iSCSI Frequently Asked Questions
================================
Q1. What is iSCSI?
==================
A1. It's an IETF standard (RFC 3720) for remote access to block-level
storage. It can be thought of as similar to NFS, except that an NFS
server exports files, which the iSCSI target exports blocks to the
iSCSI initiators, which are the clients.
Q2. What's the difference between an initiator and a target?
============================================================
A2. The target is the iSCSI server - it serves up blocks to the
clients, which are called initiators. Typically, initiators are part
of the operating system, since the operating system manages block
storage, presenting it to the user as file systems sitting on top of
the storage.
Targets do not generally need to be part of the operating system,
indeed there is some flexibility to be gained by having targets as
part of the user-level daemons that are run. This means that
security credentials need not be buried in the kernel.
Q3. So how do I use it?
=======================
A3. Firstly, you need to set up the iSCSI target. The target is
simply sitting there, waiting for requests for blocks. So we need to
configure the target with an area of storage for it to present to the
initiators.
To set up the target, you need to edit the /etc/iscsi/targets file.
It has a certain layout, to provide a means of (a) mirroring and (b)
combining multiple areas to present one large contiguous area of
storage. This can be multiply-layered.
The basic unit of storage is an extent. This can be either a file
or a device. The offset of the start of the extent to be presented
must be given, and also the length of the extent.
A device is made up of one or more extents, and/or one or more
other devices.
At the highest level, a target is what is presented to the initiator,
and is made up of one or more devices, and/or one or more extents.
The simple example is as follows, consisting of one piece of storage
presented by one target:
# extent file or device start length
extent0 /tmp/iscsi-target0 0 100MB
will produce an extent of storage which is based on one file,
/tmp/iscsi-target0, which starts 0 bytes into the file, and is 100 MB
in length. The file will be created if it does not already exist.
# target storage netmask
target0 extent0 0.0.0.0/0
That extent is then used in target0, and will be presented to an
initiator running on any host.
Extents must be defined before they can be used, and extents cannot
be used more than once.
Devices are used to combine extents or other devices. Device
definitions have the following format:
# devices
device0 RAID1 extent0 extent1
A "RAID1" device behaves in much the same way that RAID1 devices work
in the storage arena - they mirror the original storage. There can be
any number of devices or extents in a RAID1 device, not just 2, but
each device or extent must be of the same size.
A "RAID0" device combines the storage, to produce a larger area of
(virtually) "contiguous" storage.
Devices must be defined before they can be used, and devices may not
be used more than once.
A more detailed example would be as follows:
# Complex file showing 3-way RAID1 (with RAID1 components),
# also using local and (NFS) remote components
# extents
extent0 /iscsi/extents/0 0 100MB
extent1 /imports/remote1/iscsi/extents/0 0 100MB
extent2 /iscsi/extents/1 0 100MB
extent3 /imports/remote1/iscsi/extents/1 0 100MB
extent4 /iscsi/extents/2 0 100MB
extent5 /imports/remote1/iscsi/extents/2 0 100MB
extent6 /iscsi/extents/3 0 100GB
# devices
device0 RAID1 extent0 extent1
device1 RAID1 extent2 extent3
device2 RAID1 extent4 extent5
device3 RAID1 device0 device1 device2
# targets
target0 device3 10.4.0.0/16
# a target can be made from just an extent
target1 extent6 127.0.0.0/8
which will make 7 extents, 3 of them 100 MB in length and remote (via
NFS), and 3 of them 100 MB in length and local, and one of them large
(100 GB) and local. Three separate occurrences of a local and remote
100 MB extent are combined to make three RAID1 devices, and then those
three RAID1 devices are combined into another RAID1 device, and
presented as target0.
The other extent is used to present a simple 100 GB of storage as
target1.
Q4. What about security?
=========================
A4. A good question. RFC 3720 specifies CHAP, SRM and Kerberos as
methods of providing authentication and/or security. In practice,
it's whatever is provided by the initiator you are using which will
determine what authentication or security is used.
In practice, it's probably best to use ssh port forwarding for all
your traffic if you're worried about security. CHAP will only provide
authentication, the other information will flow across the network in
clear.
Q5. Using the Microsoft initiator, I can't login with CHAP
===========================================================
A5. The 1.06 Microsoft initiator silently enforces a chap password
length of at least 12 characters. If you enter a password which is
less than that, your Discovery login will silently fail.
Since CHAP provides very little authentication anyway, you are advised
not to use it - ssh port forwarding, and the use of tcp wrappers,
will do a much better job of protection anyway.
Q6. What initiators work with the NetBSD iSCSI target?
======================================================
A6. The NetBSD target has been tested at various times with the Microsoft
iSCSI initiator, version 1.06 (which can be downloaded for free from
www.microsoft.com, but needs Windows XP Pro to work), and also with the
NetBSD test harness, which is provided, but not installed, in the same
place as the target.
Q7. What is the difference between Discovery and Normal login?
===============================================================
A7. On direct-attached storage, the kernel verifies what storage is
available, and assigns a device node to it. With iSCSI, storage can
come and go, and our proximity to the devices doesn't matter. So we
need to find a different method of finding out what iSCSI storage is
out there.
This is done by a "Discovery" iSCSI session - the initiator logs in
to the target, finds out what storage is being presented, then logs
back out. This can be seen by the syslog entries:
Feb 5 10:33:44 sys3 iscsi-target: > Discovery login from iqn.1991-05.com.microsoft:inspiron on 10.4.1.5
Feb 5 10:33:44 sys3 iscsi-target: < Discovery logout from iqn.1991-05.com.microsoft:inspiron on 10.4.1.5
The initiator will then perform a "Normal" login session, which will
establish a session between the initiator and target. This is denoted
by the syslog entries:
Feb 5 00:00:28 sys3 iscsi-target: > Discovery login from iqn.1993-03.org.NetBSD.iscsi-initiator:agc on 127.0.0.1
Feb 5 00:00:28 sys3 iscsi-target: < Discovery logout from iqn.1993-03.org.NetBSD.iscsi-initiator:agc on 127.0.0.1
Feb 5 00:00:28 sys3 iscsi-target: > Normal login from iqn.1993-03.org.NetBSD.iscsi-initiator:agc on 127.0.0.1
Feb 5 00:05:32 sys3 iscsi-target: < Normal logout from iqn.1993-03.org.NetBSD.iscsi-initiator:agc on 127.0.0.1
Q8. So what do I do to try it?
==============================
A8. Perform the following steps:
a) define the storage that you want to present in /etc/iscsi/targets
b) start the iSCSI target: /etc/rc.d/iscsi_target forcestart
c) use an initiator to point it at the machine you started it on
Alistair Crooks
agc@NetBSD.org
Wed Feb 8 07:21:56 GMT 2006

64
dist/iscsi/doc/PERFORMANCE vendored Normal file
View File

@ -0,0 +1,64 @@
----------------------
USER LEVEL PERFORMANCE
----------------------
If your system is correctly configured with GbE and a GHz processor,
you should expect user level iSCSI performance similar to the following.
This output was generated by running utest against a target running uramdisk.
##BEGIN DEVICE-SPECIFIC TESTS[0:0]##
read_capacity PASSED
write_read_test PASSED
integrity_test PASSED
SCSI op 0x28: 1000 iters in 0.24 sec --> 244.38 usec
SCSI op 0x2a: 1000 iters in 0.25 sec --> 249.78 usec
SCSI op 0x25: 1000 iters in 0.25 sec --> 250.12 usec
8192 bytes/request: 8 MB written in 0.33 seconds --> 24.35 MB/sec
16384 bytes/request: 8 MB written in 0.30 seconds --> 26.74 MB/sec
32768 bytes/request: 8 MB written in 0.20 seconds --> 39.06 MB/sec
65536 bytes/request: 8 MB written in 0.15 seconds --> 52.95 MB/sec
131072 bytes/request: 8 MB written in 0.12 seconds --> 66.74 MB/sec
262144 bytes/request: 8 MB written in 0.10 seconds --> 77.76 MB/sec
8192 bytes/request: 8 MB read in 0.37 seconds --> 21.34 MB/sec
16384 bytes/request: 8 MB read in 0.19 seconds --> 41.47 MB/sec
32768 bytes/request: 8 MB read in 0.13 seconds --> 62.04 MB/sec
65536 bytes/request: 8 MB read in 0.11 seconds --> 70.99 MB/sec
131072 bytes/request: 8 MB read in 0.10 seconds --> 83.62 MB/sec
262144 bytes/request: 8 MB read in 0.09 seconds --> 92.38 MB/sec
##END DEVICE-SPECIFIC TESTS[0:0]##
------------------------
KERNEL LEVEL PERFORMANCE
------------------------
Kernel level performance (ktest to kramdisk.o) should be similar to the output
shown below. Note that this test does not go through the linux storage stack,
but is rather a kernel level iSCSI test with no attached filesystem or SCSI
midlayer.
This output was generated by installing the module intel_iscsi.o and then
running "ktest <device>" where <device> is one of your iscsi devices (e.g,
/dev/sdb). Although you specify a single device on the command line, all
target devices are tested.
##BEGIN DEVICE-SPECIFIC TESTS[0:0]##
read_capacity PASSED
write_read_test PASSED
integrity_test PASSED
SCSI op 0x28: 1000 iters in 25 jiffies --> 250 usec
SCSI op 0x2a: 1000 iters in 25 jiffies --> 250 usec
SCSI op 0x25: 1000 iters in 25 jiffies --> 250 usec
8192 bytes/request: 8388608 bytes written in 38 jiffies --> ~ 21 MB/second
16384 bytes/request: 8388608 bytes written in 38 jiffies --> ~ 21 MB/second
32768 bytes/request: 8388608 bytes written in 23 jiffies --> ~ 34 MB/second
65536 bytes/request: 8388608 bytes written in 16 jiffies --> ~ 50 MB/second
131072 bytes/request: 8388608 bytes written in 12 jiffies --> ~ 66 MB/second
262144 bytes/request: 8388608 bytes written in 10 jiffies --> ~ 79 MB/second
8192 bytes/request: 8388608 bytes read in 26 jiffies --> ~ 30 MB/second
16384 bytes/request: 8388608 bytes read in 20 jiffies --> ~ 39 MB/second
32768 bytes/request: 8388608 bytes read in 12 jiffies --> ~ 66 MB/second
65536 bytes/request: 8388608 bytes read in 12 jiffies --> ~ 66 MB/second
131072 bytes/request: 8388608 bytes read in 10 jiffies --> ~ 79 MB/second
262144 bytes/request: 8388608 bytes read in 9 jiffies --> ~ 88 MB/second
##END DEVICE-SPECIFIC TESTS[0:0]##

188
dist/iscsi/doc/README vendored Normal file
View File

@ -0,0 +1,188 @@
---------------------------------------
Intel iSCSI v20 Reference Implementation
---------------------------------------
This is a software implementation of iSCSI v20. Included in this distribution
are both host and target mode drivers with built in conformance and performance
tests, and sockets tests that can be used to simulate TCP traffic identical to
that generated between a real iSCSI host and target.
See PERFORMANCE for information regarding the expected performance of this
distribution.
This code has been successfully compiled and tested on Redhat 8.0
(kernel version 2.4.18-14) and Redhat 9.0 (kernel version 2.4.20)
with UP and SMP configurations.
-------------------
Starting the System
-------------------
1a) Modify the array in initiator.c to contain your target ip addresses and port
numbers. If you specify a TargetName there will be no discovery process. For
example, targets 0 and 2 below will first be discovered. Target 1 will not.
ISCSI_PORT is the default port defined in iscsi.h and currently set to 3260.
static INITIATOR_TARGET_T g_target[CONFIG_INITIATOR_NUM_TARGETS] = {
{"192.168.10.10", ISCSI_PORT, "", NULL, 0},
{"192.168.10.11", ISCSI_PORT, "iqn.com.intel.abc123", NULL, 0},
{"192.168.10.12", ISCSI_PORT, "", NULL, 0}};
The initiator currently only connects to one of the discovered targets. If
multiple TargetNames and TargetAddresses are returned, all but 1 are ignored.
1b) Alternately for the kernel mode driver you may specify ip addresses
in a file in the local directory called "./intel_iscsi_targets". This
file will also be looked for in the /etc directory or you may specify
the file name as a module parameter to the insmod command using the
"gfilename" argument, (insmod intel_iscsi.o gfilename="./targets").
The format for the contents of of the file is:
ip=192.168.10.10
ip=192.168.10.11 name=iqn.com.intel.abc123 port=3260
ip=192.168.10.12
The name and port fields are optional. If name is not specified, there
will be a discovery process. If port is not specified, the default port
of 3260 will be used.
1c) For the user mode intiator, if the first entry of the g_target array has ip
address "151.0.1.1", the initiator will prompt the user to enter the number
of targets and their ip addresses.
2) Modify the following constant in initiator.h accordingly:
#define CONFIG_INITIATOR_NUM_TARGETS 3
3) Run "make" to build each of:
intel_iscsi.o - kernel mode iSCSI initiator
kramdisk.o - kernel mode iSCSI target ramdisk
ufsdisk - user mode iSCSI target (disk stored as file in /tmp)
ufsdisk_mmap - same as ufsdisk, but uses mmap
uramdisk - user mode iSCSI ramdisk
utest - user mode iSCSI test suite
ktest - invokes same tests as utest, but from within device driver
usocktest - user mode sockets test that simulates iSCSI traffic
4) Start a user level target (uramdisk, ufsdisk, ufsdisk_mmap) on each target
machine:
Usage: -t <name> iSCSI TargetName (dflt "iqn.com.intel.abc123")
-p <port> Port Number (dflt 3260)
-b <block len> Block Length (dflt 512)
-n <num blocks> Number of Blocks (dflt 204800)
Or start the kernel level target (kramdisk.o):
Usage: insmod kramdisk.o port=<port>
block_len=<block length>
num_blocks=<number of blocks>
With ufsdisk and ufsdisk_mmap you can directly access a device in /dev by
creating a symbolic link in /tmp to point to the appropriate device. For
example:
"ln -s /dev/sdd /tmp/iqn.com.intel.abc123_3260_iscsi_disk_lun_0"
And kramdisk.o only operates in ramdisk mode.
5) Run utest. If you did not successfully connect to each target machine you
specified in initiator.c, then there was a problem. Make sure initiator.h
and initiator.c were correctly edited and all your targets had been started.
6) As root, run "insmod ./intel_iscsi.o." You should see output similar to the
following when either viewing /var/log/messages or running dmesg:
*********************************************
* PARAMETERS NEGOTIATED *
* *
* InitiatorName: Intel *
* InitiatorAlias: Intel *
* SessionType: normal *
* TargetName: iqn.com.intel.abc12 *
*********************************************
*********************************************
* LOGIN SUCCESSFUL *
* *
* CID: 0 *
* ISID: 0 *
* TSID: 1 *
* CmdSN: 0 *
* MaxCmdSN: 0 *
* ExpStatSN: 0 *
*********************************************
Vendor: Intel Model: Intel Labs iSCSI Rev: 2
Type: Direct-Access ANSI SCSI revision: 02
Detected scsi disk sdb at scsi2, channel 0, id 0, lun 0
SCSI device sdb: 204800 512-byte hdwr sectors (105 MB)
sdb: unknown partition table
You can now use the device as you would any other SCSI device. You can also
view driver statistics by viewing the file in /proc/scsi/iscsi. Writing to
the file (e.g. echo reset > /proc/scsi/iscsi/1) will reset all counters.
------------------
Testing the System
------------------
Once your targets and host have been started, you can test the installation
using either a single target, or by creating a RAID volume over multiple
targets.
To test a single target you can either directly read and write the device by
opening, for example, /dev/sdd. Or you can create a filesystem on the device:
fdisk /dev/sdd
mkfs /dev/sdd1
mount -t ext2 /dev/sdd1 /mnt/iscsi_fs
To test a multiple target installation, you can create a RAID volume,
virtualizing multiple targets as one SCSI device. The Linux RAID modules
will either need to be installed or compiled into the kernel. The file
/etc/raidtab must be created to reflect your targets. For example,
raiddev /dev/md0
raid-level 0
nr-raid-disks 5
persistent-superblock 0
chunk-size 64
device /dev/sdd
raid-disk 0
device /dev/sde
raid-disk 1
device /dev/sdf
raid-disk 2
device /dev/sdg
raid-disk 3
device /dev/sdh
raid-disk 4
After initialized the raid device with "mkraid /dev/md0," you can use /dev/md0
as though it were a normal SCSI device. For example,
mkfs /dev/md0
mount -t ext2 /dev/md0 /mnt/iscsi_fs
--------------------
When Things Go Wrong
--------------------
Check the kernel error messages /var/log/messages or run the dmesg command to
see any errors reported from the host driver. The targets will report target
errors to standard output.
If you need more fine grained debugging, modify the Makefile to turn on the
compilation flag CONFIG_ISCSI_DEBUG. Then run "make clean," and then "make."
You can select which type of debugging statements get printed by modifying
util.h
-------------------------------------
Interoperability with Cisco Initiator
-------------------------------------
The target is tested to be interoperable with Cisco Initiator release
3.4.1.1

58
dist/iscsi/doc/README_OSD vendored Normal file
View File

@ -0,0 +1,58 @@
-------------------------
Installing the OSD System
-------------------------
1. Build kernel version 2.4 w/ SMP mode disabled and make sure the
directory /usr/src/linux points to this build.
2. Modify initiator.h and initiator.c (as per the README) to point to
your intended target.
3. Run 'make osd' to build all the OSD executables. In particular,
you need uosd, so.o, intel_iscsi.o and osdfs.o.
4. Run 'make all' to build the remaining executables.
5. Select a machine as the target and run "uosd -f" as root on this
machine. This will create files and directories in /tmp.
----------------------
Testing the OSD System
----------------------
6. Run utest to make sure the target is working OK.
7. Do an "insmod ./so.o" to install the Linux SCSI upper layer driver for OSD.
8. Do an "insmod ./intel_iscsi.o" to install the kernel mode iSCSI initiator.
9. Do an "insmod ./osdfs.o" to install the file system.
10. Make the OSD device with "mknod /dev/so0 b 232 0".
11. Do a "mount -t osdfs /dev/so0 /mnt" to mount the filesystem.
12. Go to /mnt and run "echo Hello, World! > foo" to create an object
on the OSD.
13. Do a "cat foo" to read the object. you should see "Hello, world!"
From here you should be able to use /mnt as you would any filesystem.
--------------------
2.4.18 Modifications
--------------------
include/scsi/scsi.h:143
#define TYPE_OSD 0x0e
drivers/scsi/scsi.h:92:
#define MAX_SCSI_DEVICE_CODE 15
drivers/scsi/scsi.h:354:
#define MAX_COMMAND_SIZE 256
drivers/scsi/scsi.c:145:
"OSD ",
drivers/scsi/scsi_dma.c:248:
SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD || SDpnt->type == TYPE_OSD) {
drivers/scsi/scsi_scan.c:644:
case TYPE_OSD:
----------
Hints/Tips
----------
-Field testing on some workstations resulted in compiling errors if highmem support in the kernel as enabled

31
dist/iscsi/doc/license vendored Normal file
View File

@ -0,0 +1,31 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2004, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

1720
dist/iscsi/doc/messages.1 vendored Normal file

File diff suppressed because it is too large Load Diff

22
dist/iscsi/include/compat.h vendored Normal file
View File

@ -0,0 +1,22 @@
#ifndef COMPAT_H_
#define COMPAT_H_
#include "config.h"
#include <sys/types.h>
#define ISCSI_HTON16(a) htons(a)
#define ISCSI_HTON32(a) htonl(a)
#define ISCSI_HTON64(a) htonq(a)
#define ISCSI_NTOH16(a) ntohs(a)
#define ISCSI_NTOH32(a) ntohl(a)
#define ISCSI_NTOH64(a) ntohq(a)
u_int64_t htonq(u_int64_t);
u_int64_t ntohq(u_int64_t);
#ifndef HAVE_STRLCPY
size_t strlcpy(char *, const char *, size_t);
#endif
#endif

76
dist/iscsi/include/conffile.h vendored Normal file
View File

@ -0,0 +1,76 @@
/* $NetBSD: conffile.h,v 1.1.1.1 2006/02/08 18:56:15 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONFFILE_H_
#define CONFFILE_H_ 1
/* split routines */
#include <sys/param.h>
#include "defs.h"
DEFINE_ARRAY(strv_t, char *);
/* this struct describes a configuration file */
typedef struct conffile_t {
FILE *fp; /* in-core file pointer */
char name[MAXPATHLEN]; /* name of file */
int lineno; /* current line number */
int readonly; /* nonzero if file is readonly */
const char *sep; /* set of separators */
const char *comment; /* set of comment characters */
} conffile_t;
/* this struct describes an entry in the configuration file */
typedef struct ent_t {
char buf[BUFSIZ]; /* buffer with entry contents */
strv_t sv; /* split up string dynamic array */
} ent_t;
int conffile_open(conffile_t *, const char *, const char *, const char *, const char *);
int conffile_getent(conffile_t *, ent_t *);
int conffile_get_by_field(conffile_t *, ent_t *, int, char *);
int conffile_putent(conffile_t *, int, char *, char *);
int conffile_get_lineno(conffile_t *);
char *conffile_get_name(conffile_t *);
void conffile_printent(ent_t *);
void conffile_close(conffile_t *);
#ifndef PREFIX
#define PREFIX ""
#endif
#define _PATH_ISCSI_ETC "/etc/iscsi/"
#define _PATH_ISCSI_PASSWD PREFIX _PATH_ISCSI_ETC "auths"
#define _PATH_ISCSI_TARGETS PREFIX _PATH_ISCSI_ETC "targets"
#define _PATH_ISCSI_PID_FILE "/var/run/iscsi-target.pid"
#endif

140
dist/iscsi/include/config.h vendored Normal file
View File

@ -0,0 +1,140 @@
/* ../include/config.h. Generated by configure. */
/* ../include/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <asm/byteorder.h> header file. */
/* #undef HAVE_ASM_BYTEORDER_H */
/* Define to 1 if you have the `bswap64' function. */
#define HAVE_BSWAP64 1
/* Define to 1 if you have the <byteswap.h> header file. */
/* #undef HAVE_BYTESWAP_H */
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H 1
/* Define to 1 if you have the `daemon' function. */
#define HAVE_DAEMON 1
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if the system has the type `long long'. */
#define HAVE_LONG_LONG 1
/* Define to 1 if you have the <machine/endian.h> header file. */
#define HAVE_MACHINE_ENDIAN_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#define HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the <pthread.h> header file. */
#define HAVE_PTHREAD_H 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define to 1 if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strlcpy' function. */
#define HAVE_STRLCPY 1
/* Define to 1 if you have the `strtoll' function. */
#define HAVE_STRTOLL 1
/* Define to 1 if you have the <syslog.h> header file. */
#define HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <sys/vfs.h> header file. */
/* #undef HAVE_SYS_VFS_H */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if the system has the type `unsigned long long'. */
#define HAVE_UNSIGNED_LONG_LONG 1
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */

154
dist/iscsi/include/config.h.in vendored Normal file
View File

@ -0,0 +1,154 @@
/* ../include/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <asm/byteorder.h> header file. */
#undef HAVE_ASM_BYTEORDER_H
/* Define to 1 if you have the `asnprintf' function. */
#undef HAVE_ASNPRINTF
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* Define to 1 if you have the `bswap64' function. */
#undef HAVE_BSWAP64
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the `daemon' function. */
#undef HAVE_DAEMON
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if the system has the type `long long'. */
#undef HAVE_LONG_LONG
/* Define to 1 if you have the <machine/endian.h> header file. */
#undef HAVE_MACHINE_ENDIAN_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have the <sys/vfs.h> header file. */
#undef HAVE_SYS_VFS_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if the system has the type `unsigned long long'. */
#undef HAVE_UNSIGNED_LONG_LONG
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to 1 if you have the `vasnprintf' function. */
#undef HAVE_VASNPRINTF
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t

99
dist/iscsi/include/defs.h vendored Normal file
View File

@ -0,0 +1,99 @@
/* $NetBSD: defs.h,v 1.1.1.1 2006/02/08 18:56:15 agc Exp $ */
/*
* Copyright (c) 1999-2005 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DEFS_H_
#define DEFS_H_
#include <sys/types.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NEWARRAY(type,ptr,size,where,action) do { \
if ((ptr = (type *) calloc(sizeof(type), (unsigned)(size))) == NULL) { \
(void) fprintf(stderr, "%s: can't allocate %lu bytes\n", \
where, (unsigned long)(size * sizeof(type))); \
action; \
} \
} while( /* CONSTCOND */ 0)
#define RENEW(type,ptr,size,where,action) do { \
type *_newptr; \
if ((_newptr = (type *) realloc(ptr, sizeof(type) * (size))) == NULL) { \
(void) fprintf(stderr, "%s: can't realloc %lu bytes\n", \
where, (unsigned long)(size * sizeof(type))); \
action; \
} else { \
ptr = _newptr; \
} \
} while( /* CONSTCOND */ 0)
#define NEW(type, ptr, where, action) NEWARRAY(type, ptr, 1, where, action)
#define FREE(ptr) (void) free(ptr)
#define ALLOC(type, v, size, c, init, incr, where, action) do { \
uint32_t _newsize = size; \
if (size == 0) { \
_newsize = init; \
NEWARRAY(type, v, _newsize, where ": new", action); \
} else if (c == size) { \
_newsize = size + incr; \
RENEW(type, v, _newsize, where ": renew", action); \
} \
size = _newsize; \
} while( /* CONSTCOND */ 0)
/* (void) memset(&v[size], 0x0, sizeof(type) * incr); \*/
#define DEFINE_ARRAY(name, type) \
typedef struct name { \
uint32_t c; \
uint32_t size; \
type *v; \
} name
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef ABS
#define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#endif /* !DEFS_H_ */

52
dist/iscsi/include/device.h vendored Normal file
View File

@ -0,0 +1,52 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEVICE_H
#define _DEVICE_H
#include "iscsi.h"
#include "target.h"
/*
* Interface from target to device:
*
* device_init() initializes the device
* device_command() sends a SCSI command to one of the logical units in the device.
* device_shutdown() shuts down the device.
*/
int device_init(globals_t *, targv_t *, disc_target_t *);
int device_command(target_session_t *, target_cmd_t *);
int device_shutdown(target_session_t *);
void device_set_var(const char *, char *);
#endif /* _DEVICE_H */

157
dist/iscsi/include/driver.h vendored Normal file
View File

@ -0,0 +1,157 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Intel iSCSI Driver
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
#include "iscsi.h"
#include "util.h"
#include "initiator.h"
/*
* Driver configuration
*/
#define CONFIG_DRIVER_MAX_LUNS 1024
/*
* Internal
*/
static int driver_init(void);
static int driver_shutdown(void);
typedef struct iscsi_driver_stats_t {
unsigned num_tx, num_tx_queued;
unsigned num_rx, num_rx_queued;
unsigned avg_tx, avg_rx;
unsigned tx_queued, tx, tx_error, tx_overflow;
unsigned rx_queued, rx, rx_error, rx_overflow;
unsigned aborts_success, aborts_failed;
unsigned device_resets, bus_resets, host_resets;
iscsi_spin_t lock;
} iscsi_driver_stats_t;
/*
* Kernel Interface
*/
int iscsi_proc_info (char *, char **, off_t, int, int, int);
int iscsi_detect(Scsi_Host_Template *);
int iscsi_release(struct Scsi_Host *);
int iscsi_ioctl(Scsi_Device *dev, int cmd, void *arg);
int iscsi_command(Scsi_Cmnd *SCpnt);
int iscsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int iscsi_bios_param(Disk *, kdev_t, int *);
int iscsi_abort_handler (Scsi_Cmnd *SCpnt);
int iscsi_device_reset_handler (Scsi_Cmnd *);
int iscsi_bus_reset_handler (Scsi_Cmnd *);
int iscsi_host_reset_handler(Scsi_Cmnd *);
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,0)
int iscsi_revoke (Scsi_Device *ptr);
void iscsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *);
#endif
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
extern struct proc_dir_entry iscsi_proc_dir;
#endif
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
#define ISCSI { \
name: "Intel iSCSI Driver", \
proc_dir: NULL, \
proc_info: iscsi_proc_info, \
detect: iscsi_detect, \
bios_param: iscsi_bios_param, \
release: iscsi_release, \
revoke: NULL, \
ioctl: iscsi_ioctl, \
command: iscsi_command, \
queuecommand: iscsi_queuecommand, \
select_queue_depths: iscsi_select_queue_depths, \
eh_strategy_handler: NULL, \
eh_abort_handler: iscsi_abort_handler, \
eh_device_reset_handler: iscsi_device_reset_handler, \
eh_bus_reset_handler: iscsi_bus_reset_handler, \
eh_host_reset_handler: iscsi_host_reset_handler, \
slave_attach: NULL, \
can_queue: CONFIG_INITIATOR_QUEUE_DEPTH, \
this_id: -1, \
sg_tablesize: 128, \
cmd_per_lun: 1, /* linked commands not supported */ \
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: 0, \
use_new_eh_code: 1, \
emulated: 0, \
next: NULL, \
module: NULL, \
info: NULL, \
proc_name: "iscsi" \
}
#elif LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0)
#define ISCSI { \
name: "Intel iSCSI Driver", \
proc_dir: &iscsi_proc_dir, \
proc_info: iscsi_proc_info, \
detect: iscsi_detect, \
bios_param: iscsi_bios_param, \
release: iscsi_release, \
ioctl: iscsi_ioctl, \
command: iscsi_command, \
queuecommand: iscsi_queuecommand, \
eh_strategy_handler: NULL, \
eh_abort_handler: iscsi_abort_handler, \
eh_device_reset_handler: iscsi_device_reset_handler, \
eh_bus_reset_handler: iscsi_bus_reset_handler, \
eh_host_reset_handler: iscsi_host_reset_handler, \
use_new_eh_code: 1, \
can_queue: CONFIG_INITIATOR_QUEUE_DEPTH, \
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, /* linked commands not supported */ \
this_id: -1, \
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: 0, \
slave_attach: NULL, \
next: NULL, \
module: NULL, \
info: NULL, \
emulated: 0 \
}
#endif /* LINUX_VERSION_CODE */
#endif /* _DRIVER_H_ */

126
dist/iscsi/include/initiator.h vendored Normal file
View File

@ -0,0 +1,126 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _INITIATOR_H_
#define _INITIATOR_H_
#include "iscsi.h"
#include "parameters.h"
#define CONFIG_INITIATOR_NUM_TARGETS 1
/***********
* Private *
***********/
#define CONFIG_INITIATOR_QUEUE_DEPTH CONFIG_INITIATOR_NUM_TARGETS
#define CONFIG_INITIATOR_MAX_SESSIONS CONFIG_INITIATOR_NUM_TARGETS
enum {
INITIATOR_SESSION_STATE_INITIALIZING = 0x001,
INITIATOR_SESSION_STATE_INITIALIZED = 0x002,
INITIATOR_SESSION_STATE_CONNECTING = 0x004,
INITIATOR_SESSION_STATE_CONNECTED = 0x008,
INITIATOR_SESSION_STATE_LOGGING_IN = 0x010,
INITIATOR_SESSION_STATE_AUTHENTICATED = 0x020,
INITIATOR_SESSION_STATE_LOGGED_IN_NORMAL = 0x040,
INITIATOR_SESSION_STATE_LOGGED_IN_DISCOVERY = 0x080,
INITIATOR_SESSION_STATE_LOGGING_OUT = 0x100,
INITIATOR_SESSION_STATE_LOGGED_OUT = 0x200,
INITIATOR_SESSION_STATE_DESTROYING = 0x400
};
enum {
TARGET_HOSTNAME_SIZE = 1024,
TARGET_IP_SIZE = 16,
TARGET_NAME_SIZE = 256
};
#define INITIATOR_STATE_SHUTDOWN 1
typedef struct {
iscsi_mutex_t mutex;
iscsi_cond_t cond;
} initiator_wait_t;
typedef struct iscsi_session_t {
iscsi_socket_t sock;
uint32_t CmdSN;
uint32_t ExpStatSN;
uint32_t MaxCmdSN;
iscsi_queue_t tx_queue;
iscsi_worker_t tx_worker;
iscsi_worker_t rx_worker;
uint64_t isid;
int tsih;
int cid;
uint32_t state;
iscsi_parameter_t *params;
struct initiator_cmd_t *cmds;
iscsi_spin_t cmds_spin;
iscsi_sess_param_t sess_params;
} initiator_session_t;
typedef struct initiator_cmd_t {
void *ptr;
int type;
int (*callback) (void *);
void *callback_arg;
uint64_t isid;
int tx_done;
int status;
struct initiator_cmd_t *next;
struct initiator_cmd_t *hash_next;
uint32_t key;
} initiator_cmd_t;
typedef struct iscsi_target_t {
char name[TARGET_HOSTNAME_SIZE];
char ip[TARGET_IP_SIZE];
int port;
char TargetName[TARGET_NAME_SIZE];
initiator_session_t *sess;
int has_session;
} initiator_target_t;
/**********
* Public *
**********/
int initiator_init(const char *, const char *, int, int, int);
int initiator_info(char *, int, int);
int initiator_command(initiator_cmd_t *);
int initiator_enqueue(initiator_cmd_t *);
int initiator_abort(initiator_cmd_t *);
int initiator_shutdown(void);
#endif /* _INITIATOR_H_ */

518
dist/iscsi/include/iscsi.h vendored Normal file
View File

@ -0,0 +1,518 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ISCSI_H
#define ISCSI_H
#include "util.h"
/*
* iSCSI Version 18
*/
#define ISCSI_VENDOR "NetBSD"
#define ISCSI_PRODUCT "NetBSD/Intel iSCSI"
#define ISCSI_VERSION 0
/*
* Parameters
*/
#define ISCSI_IMMEDIATE_DATA_DFLT 1
#define ISCSI_INITIAL_R2T_DFLT 1
#define ISCSI_USE_PHASE_COLLAPSED_READ_DFLT 0
#define ISCSI_HEADER_LEN 48
#define ISCSI_PORT 3260 /* Default port */
#define ISCSI_OPCODE(HEADER) (HEADER[0]&0x3f)
#define ISCSI_FIRST_BURST (ISCSI_FIRST_BURST_DFLT)
#define ISCSI_DATA_PDU_LENGTH (ISCSI_DATA_PDU_LENGTH_DFLT)
/*
* Opcodes
*/
#define ISCSI_NOP_OUT 0x00
#define ISCSI_SCSI_CMD 0x01
#define ISCSI_TASK_CMD 0x02
#define ISCSI_LOGIN_CMD 0x03
#define ISCSI_TEXT_CMD 0x04
#define ISCSI_WRITE_DATA 0x05
#define ISCSI_LOGOUT_CMD 0x06
#define ISCSI_NOP_IN 0x20
#define ISCSI_SCSI_RSP 0x21
#define ISCSI_TASK_RSP 0x22
#define ISCSI_LOGIN_RSP 0x23
#define ISCSI_TEXT_RSP 0x24
#define ISCSI_READ_DATA 0x25
#define ISCSI_LOGOUT_RSP 0x26
#define ISCSI_R2T 0x31
#define ISCSI_REJECT 0x3f
#define ISCSI_SNACK 0x10/* not implemented */
#define ISCSI_ASYNC 0x32
/*
* Login Phase
*/
#define ISCSI_LOGIN_STATUS_SUCCESS 0
#define ISCSI_LOGIN_STATUS_REDIRECTION 1
#define ISCSI_LOGIN_STATUS_INITIATOR_ERROR 2
#define ISCSI_LOGIN_STATUS_TARGET_ERROR 3
#define ISCSI_LOGIN_STAGE_SECURITY 0
#define ISCSI_LOGIN_STAGE_NEGOTIATE 1
#define ISCSI_LOGIN_STAGE_FULL_FEATURE 3
/*
* Logout Phase
*/
#define ISCSI_LOGOUT_CLOSE_SESSION 0
#define ISCSI_LOGOUT_CLOSE_CONNECTION 1
#define ISCSI_LOGOUT_CLOSE_RECOVERY 2
#define ISCSI_LOGOUT_STATUS_SUCCESS 0
#define ISCSI_LOGOUT_STATUS_NO_CID 1
#define ISCSI_LOGOUT_STATUS_NO_RECOVERY 2
#define ISCSI_LOGOUT_STATUS_FAILURE 3
/*
* Task Command
*/
#define ISCSI_TASK_CMD_ABORT_TASK 1
#define ISCSI_TASK_CMD_ABORT_TASK_SET 2
#define ISCSI_TASK_CMD_CLEAR_ACA 3
#define ISCSI_TASK_CMD_CLEAR_TASK_SET 4
#define ISCSI_TASK_CMD_LOGICAL_UNIT_RESET 5
#define ISCSI_TASK_CMD_TARGET_WARM_RESET 6
#define ISCSI_TASK_CMD_TARGET_COLD_RESET 7
#define ISCSI_TASK_CMD_TARGET_REASSIGN 8
typedef struct iscsi_task_cmd_t {
int32_t immediate;
uint8_t function;
uint64_t lun;
uint32_t tag;
uint32_t ref_tag;
uint32_t CmdSN;
uint32_t ExpStatSN;
uint32_t RefCmdSN;
uint32_t ExpDataSN;
} iscsi_task_cmd_t;
int iscsi_task_cmd_encap(uint8_t *header, iscsi_task_cmd_t * cmd);
int iscsi_task_cmd_decap(uint8_t *header, iscsi_task_cmd_t * cmd);
/*
* Task Response
*/
#define ISCSI_TASK_RSP_FUNCTION_COMPLETE 0
#define ISCSI_TASK_RSP_NO_SUCH_TASK 1
#define ISCSI_TASK_RSP_NO_SUCH_LUN 2
#define ISCSI_TASK_RSP_STILL_ALLEGIANT 3
#define ISCSI_TASK_RSP_NO_FAILOVER 4
#define ISCSI_TASK_RSP_NO_SUPPORT 5
#define ISCSI_TASK_RSP_AUTHORIZED_FAILED 6
#define ISCSI_TASK_RSP_REJECTED 255
#define ISCSI_TASK_QUAL_FUNCTION_EXECUTED 0
#define ISCSI_TASK_QUAL_NOT_AUTHORIZED 1
typedef struct iscsi_task_rsp_t {
uint8_t response;
uint32_t length;
uint32_t tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
} iscsi_task_rsp_t;
int iscsi_task_rsp_encap(uint8_t *header, iscsi_task_rsp_t * rsp);
int iscsi_task_rsp_decap(uint8_t *header, iscsi_task_rsp_t * rsp);
/*
* NOP-Out
*/
typedef struct iscsi_nop_out_args_t {
int32_t immediate;
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t CmdSN;
uint32_t ExpStatSN;
const uint8_t *data;
} iscsi_nop_out_args_t;
int iscsi_nop_out_encap(uint8_t *header, iscsi_nop_out_args_t * cmd);
int iscsi_nop_out_decap(uint8_t *header, iscsi_nop_out_args_t * cmd);
/*
* NOP-In
*/
typedef struct iscsi_nop_in_args_t {
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
} iscsi_nop_in_args_t;
int iscsi_nop_in_encap(uint8_t *header, iscsi_nop_in_args_t * cmd);
int iscsi_nop_in_decap(uint8_t *header, iscsi_nop_in_args_t * cmd);
/*
* Text Command
*/
typedef struct iscsi_text_cmd_args_t {
int32_t immediate;
int32_t final;
int32_t cont;
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t CmdSN;
uint32_t ExpStatSN;
char *text;
} iscsi_text_cmd_args_t;
int iscsi_text_cmd_encap(uint8_t *header, iscsi_text_cmd_args_t * cmd);
int iscsi_text_cmd_decap(uint8_t *header, iscsi_text_cmd_args_t * cmd);
/*
* Text Response
*/
typedef struct iscsi_text_rsp_args_t {
int32_t final;
int32_t cont;
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
} iscsi_text_rsp_args_t;
int iscsi_text_rsp_encap(uint8_t *header, iscsi_text_rsp_args_t * rsp);
int iscsi_text_rsp_decap(uint8_t *header, iscsi_text_rsp_args_t * rsp);
/*
* Login Command
*/
typedef struct iscsi_login_cmd_args_t {
int32_t transit;
int32_t cont;
uint8_t csg;
uint8_t nsg;
int8_t version_max;
int8_t version_min;
uint8_t AHSlength;
uint32_t length;
uint64_t isid;
uint16_t tsih;
uint32_t tag;
uint16_t cid;
uint32_t CmdSN;
uint32_t ExpStatSN;
char *text;
} iscsi_login_cmd_args_t;
int iscsi_login_cmd_encap(uint8_t *header, iscsi_login_cmd_args_t * cmd);
int iscsi_login_cmd_decap(uint8_t *header, iscsi_login_cmd_args_t * cmd);
/*
* Login Response
*/
typedef struct iscsi_login_rsp_args_t {
int32_t transit;
int32_t cont;
uint8_t csg;
uint8_t nsg;
int8_t version_max;
int8_t version_active;
uint8_t AHSlength;
uint32_t length;
uint64_t isid;
uint16_t tsih;
uint32_t tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint8_t status_class;
uint8_t status_detail;
} iscsi_login_rsp_args_t;
int iscsi_login_rsp_encap(uint8_t *header, iscsi_login_rsp_args_t * rsp);
int iscsi_login_rsp_decap(uint8_t *header, iscsi_login_rsp_args_t * rsp);
/*
* Logout Command
*/
typedef struct iscsi_logout_cmd_args_t {
int32_t immediate;
uint8_t reason;
uint32_t tag;
uint16_t cid;
uint32_t CmdSN;
uint32_t ExpStatSN;
} iscsi_logout_cmd_args_t;
int iscsi_logout_cmd_encap(uint8_t *header, iscsi_logout_cmd_args_t * cmd);
int iscsi_logout_cmd_decap(uint8_t *header, iscsi_logout_cmd_args_t * cmd);
/*
* Logout Response
*/
typedef struct iscsi_logout_rsp_args_t {
uint8_t response;
uint32_t length;
uint32_t tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint16_t Time2Wait;
uint16_t Time2Retain;
} iscsi_logout_rsp_args_t;
int iscsi_logout_rsp_encap(uint8_t *header, iscsi_logout_rsp_args_t * rsp);
int iscsi_logout_rsp_decap(uint8_t *header, iscsi_logout_rsp_args_t * rsp);
/*
* SCSI Command
*/
typedef struct iscsi_scsi_cmd_args_t {
int32_t immediate;
int32_t final;
int32_t input;
int32_t output;
uint8_t attr;
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t trans_len;
uint32_t bidi_trans_len;
uint32_t CmdSN;
uint32_t ExpStatSN;
uint8_t *cdb;
uint8_t *ext_cdb;
uint8_t *ahs;
uint8_t ahs_len;
uint8_t *send_data;
int32_t send_sg_len;
uint8_t *recv_data;
int32_t recv_sg_len;
uint8_t status;
uint32_t bytes_sent;
uint32_t bytes_recv;
} iscsi_scsi_cmd_args_t;
int iscsi_scsi_cmd_encap(uint8_t *header, iscsi_scsi_cmd_args_t * cmd);
int iscsi_scsi_cmd_decap(uint8_t *header, iscsi_scsi_cmd_args_t * cmd);
/*
* SCSI Response
*/
typedef struct iscsi_scsi_rsp_args_t {
int32_t bidi_overflow;
int32_t bidi_underflow;
int32_t overflow;
int32_t underflow;
uint8_t response;
uint8_t status;
uint32_t ahs_len;
uint32_t length;
uint32_t tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t ExpDataSN;
uint32_t bidi_res_cnt;
uint32_t basic_res_cnt;
} iscsi_scsi_rsp_t;
int iscsi_scsi_rsp_encap(uint8_t *header, iscsi_scsi_rsp_t * rsp);
int iscsi_scsi_rsp_decap(uint8_t *header, iscsi_scsi_rsp_t * rsp);
/*
* Ready To Transfer (R2T)
*/
typedef struct iscsi_r2t_args_t {
uint32_t AHSlength;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t R2TSN;
uint32_t offset;
uint32_t length;
} iscsi_r2t_t;
int iscsi_r2t_encap(uint8_t *header, iscsi_r2t_t * cmd);
int iscsi_r2t_decap(uint8_t *header, iscsi_r2t_t * cmd);
/*
* SCSI Write Data
*/
typedef struct iscsi_write_data_args_t {
int32_t final;
uint32_t length;
uint64_t lun;
uint32_t tag;
uint32_t transfer_tag;
uint32_t ExpStatSN;
uint32_t DataSN;
uint32_t offset;
} iscsi_write_data_t;
int iscsi_write_data_encap(uint8_t *header, iscsi_write_data_t * cmd);
int iscsi_write_data_decap(uint8_t *header, iscsi_write_data_t * cmd);
/*
* SCSI Read Data
*/
typedef struct iscsi_read_data_args_t {
int32_t final;
int32_t ack;
int32_t overflow;
int32_t underflow;
int32_t S_bit;
uint8_t status;
uint32_t length;
uint64_t lun;
uint32_t task_tag;
uint32_t transfer_tag;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t DataSN;
uint32_t offset;
uint32_t res_count;
} iscsi_read_data_t;
int iscsi_read_data_encap(uint8_t *header, iscsi_read_data_t * cmd);
int iscsi_read_data_decap(uint8_t *header, iscsi_read_data_t * cmd);
/*
* Reject
*/
typedef struct iscsi_reject_args_t {
uint8_t reason;
uint32_t length;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t DataSN;
char *header;
} iscsi_reject_t;
int iscsi_reject_encap(uint8_t *header, iscsi_reject_t * cmd);
int iscsi_reject_decap(uint8_t *header, iscsi_reject_t * cmd);
/*
* Async Message
*/
typedef struct iscsi_async_msg_args_t {
uint8_t AHSlength;
uint64_t lun;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t length;
uint8_t AsyncEvent;
uint8_t AsyncVCode;
} iscsi_async_msg_t;
int iscsi_amsg_decap(uint8_t *header, iscsi_async_msg_t * msg);
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
#endif /* ISCSI_H */

54
dist/iscsi/include/md5.h vendored Normal file
View File

@ -0,0 +1,54 @@
/*
* This is the header file for the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*
* Changed so as no longer to depend on Colin Plumb's `usual.h'
* header definitions; now uses stuff from dpkg's config.h
* - Ian Jackson <ijackson@nyx.cs.du.edu>.
* Still in the public domain.
*/
#ifndef MD5_H
#define MD5_H
typedef uint32_t UWORD32;
#ifdef __cplusplus
extern "C" {
#endif
#define md5byte uint8_t
struct MD5Context {
UWORD32 buf[4];
UWORD32 bytes[2];
UWORD32 in[16];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, md5byte const *buf, uint32_t len);
void MD5Final(uint8_t digest[16], struct MD5Context *context);
void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
#ifdef __cplusplus
}
#endif
#endif /* !MD5_H */

145
dist/iscsi/include/osd.h vendored Normal file
View File

@ -0,0 +1,145 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OSD_H
#define OSD_H
#ifndef __KERNEL__
#include <stdint.h>
#endif
#include "util.h"
#define OSD_VENDOR "NetBSD"
#define OSD_PRODUCT "NetBSD/Intel OSD"
#define OSD_VERSION 0
/*
* OSD Configuration
*/
#define CONFIG_OSD_CAPACITY_DFLT 1024
#define CONFIG_OSD_LUNS_DFLT 1
#define CONFIG_OSD_BASEDIR_DFLT "/tmp/iscsi_osd"
#define CONFIG_OSD_CDB_LEN 128
/*
* OSD Service Actions
*/
#define OSD_CREATE_GROUP 0x880B
#define OSD_REMOVE_GROUP 0x880C
#define OSD_CREATE 0x8802
#define OSD_REMOVE 0x880A
#define OSD_READ 0x8805
#define OSD_WRITE 0x8806
#define OSD_GET_ATTR 0x880E
#define OSD_SET_ATTR 0x880F
/*
* OSD Arguments
*/
typedef struct osd_args_t {
uint8_t opcode;
uint8_t control;
uint8_t security;
uint8_t add_cdb_len;
uint16_t service_action;
uint8_t options_byte;
uint8_t second_options_byte;
uint32_t GroupID;
uint64_t UserID;
uint32_t SessionID;
uint64_t length;
uint64_t offset;
uint32_t set_attributes_list_length;
uint32_t get_attributes_page;
uint32_t get_attributes_list_length;
uint32_t get_attributes_allocation_length;
} osd_args_t;
#define OSD_ENCAP_CDB(ARGS, CDB) \
(CDB)[0] = (ARGS)->opcode; \
(CDB)[1] = (ARGS)->control; \
(CDB)[6] = (ARGS)->security; \
(CDB)[7] = (ARGS)->add_cdb_len; \
*((uint16_t *)((CDB)+8)) = ISCSI_HTONS((ARGS)->service_action); \
(CDB)[10] = (ARGS)->options_byte; \
(CDB)[11] = (ARGS)->second_options_byte; \
*((uint32_t *)((CDB)+12)) = ISCSI_HTONL((ARGS)->GroupID); \
*((uint64_t *)((CDB)+16)) = ISCSI_HTONLL((ARGS)->UserID); \
*((uint32_t *)((CDB)+24)) = ISCSI_HTONL((ARGS)->SessionID); \
*((uint64_t *)((CDB)+28)) = ISCSI_HTONLL((ARGS)->length); \
*((uint64_t *)((CDB)+36)) = ISCSI_HTONLL((ARGS)->offset); \
*((uint32_t *)((CDB)+44)) = ISCSI_HTONL((ARGS)->get_attributes_page); \
*((uint32_t *)((CDB)+48)) = ISCSI_HTONL((ARGS)->get_attributes_list_length); \
*((uint32_t *)((CDB)+52)) = ISCSI_HTONL((ARGS)->get_attributes_allocation_length); \
*((uint32_t *)((CDB)+72)) = ISCSI_HTONL((ARGS)->set_attributes_list_length);
#define OSD_DECAP_CDB(CDB, EXT_CDB, ARGS) \
(ARGS)->opcode = (CDB)[0]; \
(ARGS)->control = (CDB)[1]; \
(ARGS)->security = (CDB)[6]; \
(ARGS)->add_cdb_len = (CDB)[7]; \
(ARGS)->service_action = ISCSI_NTOHS(*((uint16_t *)((CDB)+8))); \
(ARGS)->options_byte = (CDB)[10]; \
(ARGS)->second_options_byte = (CDB)[11]; \
(ARGS)->GroupID = ISCSI_NTOHL(*((uint32_t *)((CDB)+12))); \
(ARGS)->UserID = ISCSI_NTOHLL(*((uint64_t *)((EXT_CDB)-16+16))); \
(ARGS)->SessionID = ISCSI_NTOHL(*((uint32_t *)((EXT_CDB)-16+24))); \
(ARGS)->length = ISCSI_NTOHLL(*((uint64_t *)((EXT_CDB)-16+28))); \
(ARGS)->offset = ISCSI_NTOHLL(*((uint64_t *)((EXT_CDB)-16+36))); \
(ARGS)->get_attributes_page = ISCSI_NTOHL(*((uint32_t *)((EXT_CDB)-16+44))); \
(ARGS)->get_attributes_list_length = ISCSI_NTOHL(*((uint32_t *)((EXT_CDB)-16+48))); \
(ARGS)->get_attributes_allocation_length = ISCSI_NTOHL(*((uint32_t *)((EXT_CDB)-16+52))); \
(ARGS)->set_attributes_list_length = ISCSI_NTOHL(*((uint32_t *)((EXT_CDB)-16+72)));
#define OSD_PRINT_CDB(CDB, EXT_CDB) \
PRINT("opcode = 0x%x\n", CDB[0]); \
PRINT("control = 0x%x\n", CDB[1]); \
PRINT("security = 0x%x\n", CDB[6]); \
PRINT("add_cdb_len = %u\n", CDB[7]); \
PRINT("service_action = 0x%x\n", ISCSI_NTOHS(*(uint16_t*)(CDB+8))); \
PRINT("options byte 1 = 0x%x\n", CDB[10]); \
PRINT("options byte 2 = 0x%x\n", CDB[11]); \
PRINT("group id = 0x%x\n", ISCSI_NTOHL(*(uint32_t*)(CDB+12))); \
PRINT("user id = 0x%llx\n", ISCSI_NTOHLL(*(uint64_t*)(EXT_CDB-16+16))); \
PRINT("session id = 0x%x\n", ISCSI_NTOHL(*(uint32_t*)(EXT_CDB-16+24))); \
PRINT("length = %llu\n", ISCSI_NTOHLL(*(uint64_t*)(EXT_CDB-16+28))); \
PRINT("offset = %llu\n", ISCSI_NTOHLL(*(uint64_t*)(EXT_CDB-16+36))); \
PRINT("get attr page = %u\n", ISCSI_NTOHL(*(uint32_t*)(EXT_CDB-16+44))); \
PRINT("get list len = %u\n", ISCSI_NTOHL(*(uint32_t*)(EXT_CDB-16+48))); \
PRINT("get alloc len = %u\n", ISCSI_NTOHL(*(uint32_t*)(EXT_CDB-16+52))); \
PRINT("set list len = %u\n", ISCSI_NTOHL(*(uint32_t*)(EXT_CDB-16+72)));
#endif /* OSD_H */

61
dist/iscsi/include/osd_ops.h vendored Normal file
View File

@ -0,0 +1,61 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2002, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Transport-independent Methods
*/
#ifndef _OSD_OPS_H_
#define _OSD_OPS_H_
#include "osd.h"
typedef struct osd_ops_mem {
const void *send_data;
uint64_t send_len;
int send_sg;
void *recv_data;
uint64_t recv_len;
int recv_sg;
} OSD_OPS_MEM;
int osd_create_group(void *, int (*)(void *, osd_args_t *, OSD_OPS_MEM *), uint32_t *);
int osd_remove_group(void *, uint32_t , int (*)(void *, osd_args_t *, OSD_OPS_MEM *));
int osd_create(void *, uint32_t , int (*)(void *, osd_args_t *, OSD_OPS_MEM *), uint64_t *);
int osd_remove(void *, uint32_t , uint64_t , int (*)(void *, osd_args_t *, OSD_OPS_MEM *));
int osd_write(void *, uint32_t , uint64_t , uint64_t , uint64_t , const void *, int , int (*)(void *, osd_args_t *, OSD_OPS_MEM *));
int osd_read(void *, uint32_t , uint64_t , uint64_t , uint64_t , void *, int , int (*)(void *, osd_args_t *, OSD_OPS_MEM *));
int osd_set_one_attr(void *, uint32_t , uint64_t , uint32_t , uint32_t , uint32_t , void *, int (*)(void *, osd_args_t *, OSD_OPS_MEM *));
int osd_get_one_attr(void *, uint32_t , uint64_t , uint32_t , uint32_t , uint32_t , int (*)(void *, osd_args_t *, OSD_OPS_MEM *), uint16_t *, void *);
#endif

176
dist/iscsi/include/parameters.h vendored Normal file
View File

@ -0,0 +1,176 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PARAMETERS_H_
#define _PARAMETERS_H_
typedef struct MD5Context MD5Context_t;
#define ISCSI_PARAM_MAX_LEN 256
#define ISCSI_PARAM_KEY_LEN 64
/* Parameter Type */
#define ISCSI_PARAM_TYPE_DECLARATIVE 1
#define ISCSI_PARAM_TYPE_DECLARE_MULTI 2 /* for TargetName and
* TargetAddress */
#define ISCSI_PARAM_TYPE_NUMERICAL 3
#define ISCSI_PARAM_TYPE_NUMERICAL_Z 4 /* zero represents no limit */
#define ISCSI_PARAM_TYPE_BINARY_OR 5
#define ISCSI_PARAM_TYPE_BINARY_AND 6
#define ISCSI_PARAM_TYPE_LIST 7
#define ISCSI_CHAP_DATA_LENGTH 16
#define ISCSI_CHAP_STRING_LENGTH 256
/* XXX - agc */
#define ISCSI_CHAP_INUSER "alice"
#define ISCSI_CHAP_INPASSWORD "alicePass"
#define ISCSI_CHAP_OUTUSER "tommas"
#define ISCSI_CHAP_OUTPASSWORD "tomPass"
#define ISCSI_PARAM_STATUS_AUTH_FAILED -2
#define ISCSI_PARAM_STATUS_FAILED -1
/* types of authentication which the initiator can select */
enum {
AuthNone,
AuthCHAP,
AuthKerberos,
AuthSRP
};
/* types of digest which the initiator can select */
enum {
DigestNone = 0x0,
DigestHeader = 0x01,
DigestData = 0x02
/* these are bit masks, extend accordingly */
};
typedef struct iscsi_parameter_item_t {
char value[ISCSI_PARAM_MAX_LEN];
struct iscsi_parameter_item_t *next;
} iscsi_parameter_value_t;
/* XXX - agc */
/* this struct defines the credentials a user has */
typedef struct cred_t {
char *user; /* user's name */
char *auth_type; /* preferred authentication type */
char *shared_secret; /* the shared secret which will be used */
} cred_t;
/*
* Structure for storing negotiated parameters that are frequently accessed
* on an active session
*/
typedef struct iscsi_sess_param_t {
uint32_t max_burst_length;
uint32_t first_burst_length;
uint32_t max_data_seg_length;
cred_t cred;
uint8_t initial_r2t;
uint8_t immediate_data;
uint8_t header_digest;
uint8_t data_digest;
uint8_t auth_type;
uint8_t mutual_auth;
uint8_t digest_wanted;
} iscsi_sess_param_t;
typedef struct iscsi_parameter_t {
char key[ISCSI_PARAM_KEY_LEN]; /* key */
int type; /* type of parameter */
char valid[ISCSI_PARAM_MAX_LEN]; /* list of valid values */
char dflt[ISCSI_PARAM_MAX_LEN]; /* default value */
iscsi_parameter_value_t *value_l; /* value list */
char offer_rx[ISCSI_PARAM_MAX_LEN]; /* outgoing offer */
char offer_tx[ISCSI_PARAM_MAX_LEN]; /* incoming offer */
char answer_tx[ISCSI_PARAM_MAX_LEN]; /* outgoing answer */
char answer_rx[ISCSI_PARAM_MAX_LEN]; /* incoming answer */
char negotiated[ISCSI_PARAM_MAX_LEN]; /* negotiated value */
int tx_offer; /* sent offer */
int rx_offer; /* received offer */
int tx_answer; /* sent answer */
int rx_answer; /* received answer */
int reset; /* reset value_l */
struct iscsi_parameter_t *next;
} iscsi_parameter_t;
int param_list_add(iscsi_parameter_t ** , int , const char *, const char *, const char *);
int param_list_print(iscsi_parameter_t * );
int param_list_destroy(iscsi_parameter_t * );
int param_text_add(iscsi_parameter_t *, const char *, const char *, char *, int *, int, int );
int param_text_parse(iscsi_parameter_t *, cred_t *, char *, int , char *, int *, int, int);
int param_text_print(char *, uint32_t );
int param_num_vals(iscsi_parameter_t * , char *);
int param_val_reset(iscsi_parameter_t * , const char *);
char *param_val(iscsi_parameter_t * , const char *);
char *param_val_which(iscsi_parameter_t * , const char *, int );
char *param_offer(iscsi_parameter_t * , char *);
char *param_answer(iscsi_parameter_t * , char *);
iscsi_parameter_t *param_get(iscsi_parameter_t * , const char *);
int driver_atoi(const char *);
int param_atoi(iscsi_parameter_t * , const char *);
int param_equiv(iscsi_parameter_t * , const char *, const char *);
int param_commit(iscsi_parameter_t * );
void set_session_parameters(iscsi_parameter_t * , iscsi_sess_param_t * );
/*
* Macros
*/
#define PARAM_LIST_DESTROY(LIST, ELSE) \
if (param_list_destroy(LIST)!=0) { \
TRACE_ERROR("param_list_destroy() failed\n"); \
ELSE; \
}
#define PARAM_LIST_ADD(LIST, TYPE, KEY, DFLT, VALID, ELSE) \
if (param_list_add(LIST, TYPE, KEY, DFLT, VALID)!=0) { \
TRACE_ERROR("param_list_add() failed\n"); \
ELSE; \
}
#define PARAM_TEXT_ADD(LIST, KEY, VAL, TEXT, LEN, SIZE, OFFER, ELSE ) \
if (param_text_add(LIST, KEY, VAL, TEXT, LEN, SIZE, OFFER)!=0) { \
TRACE_ERROR("param_text_add() failed\n"); \
ELSE; \
}
#define PARAM_TEXT_PARSE(LIST, CRED, TEXT, LEN, TEXT_OUT, LEN_OUT, SIZE, OFFER, ELSE ) \
if (param_text_parse(LIST, CRED, TEXT, LEN, TEXT_OUT, LEN_OUT, SIZE, OFFER)!=0) { \
TRACE_ERROR("param_text_parse_offer() failed\n"); \
ELSE; \
}
#endif

25
dist/iscsi/include/scsi_cmd_codes.h vendored Normal file
View File

@ -0,0 +1,25 @@
/* taken from http://www.arkeia.com/resources/scsi_rsc.html */
#ifndef SCSI_CMD_CODES_H_
#define SCSI_CMD_CODES_H_
enum {
TEST_UNIT_READY = 0x00,
WRITE_6 = 0x06,
READ_6 = 0x08,
INQUIRY = 0x12,
MODE_SENSE_6 = 0x1a,
READ_CAPACITY = 0x25,
READ_10 = 0x28,
WRITE_10 = 0x2a,
VERIFY = 0x2f,
MODE_SENSE_10 = 0x5a,
REPORT_LUNS = 0xa0
};
#define SIX_BYTE_COMMAND(op) ((op) <= 0x1f)
#define TEN_BYTE_COMMAND(op) ((op) > 0x1f && (op) <= 0x5f)
#define ISCSI_MODE_SENSE_LEN 11
#endif /* !SCSI_CMD_CODES_H_ */

56
dist/iscsi/include/so.h vendored Normal file
View File

@ -0,0 +1,56 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2002, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SO_H
#define _SO_H
#ifndef _SCSI_H
#include "scsi.h"
#endif
#ifndef _GENDISK_H
#include <linux/genhd.h>
#endif
typedef struct scsi_osd {
Scsi_Device *device;
unsigned capacity; /* size in blocks */
unsigned char ready; /* flag ready for FLOPTICAL */
unsigned char write_prot; /* flag write_protect for rmvable dev */
unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */
unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
unsigned has_part_table:1; /* has partition table */
} Scsi_Osd;
#endif

86
dist/iscsi/include/storage.h vendored Normal file
View File

@ -0,0 +1,86 @@
/* $NetBSD: storage.h,v 1.1.1.1 2006/02/08 18:56:15 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STORAGE_H_
#define STORAGE_H_
#include "defs.h"
enum {
DE_EXTENT,
DE_DEVICE
};
/* a device can be made up of an extent or another device */
typedef struct disc_de_t {
int32_t type; /* device or extent */
uint64_t size; /* size of underlying extent or device */
union {
struct disc_extent_t *xp; /* pointer to extent */
struct disc_device_t *dp; /* pointer to device */
} u;
} disc_de_t;
/* this struct describes an extent of storage */
typedef struct disc_extent_t {
char *extent; /* extent name */
char *dev; /* device associated with it */
uint64_t sacred; /* offset of extent from start of device */
uint64_t len; /* size of extent */
int fd; /* in-core file descriptor */
int used; /* extent has been used in a device */
} disc_extent_t;
DEFINE_ARRAY(extv_t, disc_extent_t);
/* this struct describes a device */
typedef struct disc_device_t {
char *dev; /* device name */
int raid; /* RAID level */
uint64_t off; /* current offset in device */
uint64_t len; /* size of device */
uint32_t size; /* size of device/extent array */
uint32_t c; /* # of entries in device/extents */
disc_de_t *xv; /* device/extent array */
int used; /* device has been used in a device/target */
} disc_device_t;
DEFINE_ARRAY(devv_t, disc_device_t);
/* this struct describes an iscsi target's associated features */
typedef struct disc_target_t {
char *target; /* target name */
disc_de_t de; /* pointer to its device */
uint16_t port; /* port to listen on */
char *mask; /* mask to export it to */
} disc_target_t;
DEFINE_ARRAY(targv_t, disc_target_t);
#endif /* !STORAGE_H_ */

100
dist/iscsi/include/target.h vendored Normal file
View File

@ -0,0 +1,100 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TARGET_H_
#define _TARGET_H_
#include "iscsi.h"
#include "util.h"
#include "parameters.h"
#include "storage.h"
/* Default configuration */
#define DEFAULT_TARGET_MAX_SESSIONS 4 /* n+1 */
#define DEFAULT_TARGET_NUM_LUNS 1
#define DEFAULT_TARGET_BLOCK_LEN 512
#define DEFAULT_TARGET_NUM_BLOCKS 204800
#define DEFAULT_TARGET_NAME "iqn.1993-03.org.netbsd.iscsi-target"
#define DEFAULT_TARGET_QUEUE_DEPTH 8
#define DEFAULT_TARGET_TCQ 0
enum {
MAX_TGT_NAME_SIZE = 512,
MAX_INITIATOR_ADDRESS_SIZE = 256
};
/* global variables, moved from target.c */
typedef struct globals_t {
char targetname[MAX_TGT_NAME_SIZE];
uint16_t port;
iscsi_socket_t sock;
int state;
int listener_pid;
volatile int listener_listening;
char targetaddress[MAX_TGT_NAME_SIZE]; /* iSCSI TargetAddress set after iscsi_sock_accept() */
} globals_t;
typedef struct target_session_t {
int id;
int d;
iscsi_socket_t sock;
uint16_t cid;
uint32_t StatSN;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint8_t *buff;
int UsePhaseCollapsedRead;
int IsFullFeature;
int IsLoggedIn;
int LoginStarted;
uint64_t isid;
int tsih;
globals_t *globals;
iscsi_worker_t worker;
iscsi_parameter_t *params;
iscsi_sess_param_t sess_params;
char initiator[MAX_INITIATOR_ADDRESS_SIZE];
} target_session_t;
typedef struct target_cmd_t {
iscsi_scsi_cmd_args_t *scsi_cmd;
int (*callback) (void *);
void *callback_arg;
} target_cmd_t;
int target_init(globals_t *, targv_t *, char *, int);
int target_shutdown(globals_t *);
int target_listen(globals_t *);
int target_transfer_data(target_session_t *, iscsi_scsi_cmd_args_t *, struct iovec *, int);
#endif /* _TARGET_H_ */

50
dist/iscsi/include/tests.h vendored Normal file
View File

@ -0,0 +1,50 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCSI_TEST_H
#define _SCSI_TEST_H
#include "initiator.h"
int test_all(int , int );
int integrity_test(uint32_t , uint32_t , uint32_t , int );
int nop_test(uint32_t , uint32_t , uint32_t );
int latency_test(uint64_t , uint32_t , uint8_t , uint32_t );
int throughput_test(uint32_t , uint32_t , uint32_t , uint32_t , uint32_t , int , int );
int read_or_write(uint64_t , uint32_t , uint32_t , uint32_t , uint32_t , uint8_t *, int , int );
int nop_out(uint64_t , int , int , int , const char *);
int read_capacity(uint64_t , uint32_t , uint32_t *, uint32_t *);
int write_read_test(uint64_t , uint32_t , int );
int scatter_gather_test(uint64_t , uint32_t , uint8_t );
#endif

609
dist/iscsi/include/util.h vendored Normal file
View File

@ -0,0 +1,609 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UTIL_H_
#define _UTIL_H_
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
/*
*
*/
#define ISCSI_HTONLL6(x) (uint64_t) \
( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40)))
#define ISCSI_NTOHLL6(x) (uint64_t) \
( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24)) \
| ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40)))
/*
* Debugging Levels
*/
#define TRACE_NET_DEBUG 0x00000001
#define TRACE_NET_BUFF 0x00000002
#define TRACE_NET_IOV 0x00000004
#define TRACE_NET_ALL (TRACE_NET_DEBUG|TRACE_NET_BUFF|TRACE_NET_IOV)
#define TRACE_ISCSI_DEBUG 0x00000010
#define TRACE_ISCSI_CMD 0x00000020
#define TRACE_ISCSI_ARGS 0x00000040
#define TRACE_ISCSI_PARAM 0x00000080
#define TRACE_ISCSI_ALL (TRACE_ISCSI_DEBUG|TRACE_ISCSI_ARGS|TRACE_ISCSI_PARAM|TRACE_ISCSI_CMD)
#define TRACE_SCSI_DEBUG 0x00000100
#define TRACE_SCSI_CMD 0x00000200
#define TRACE_SCSI_DATA 0x00000400
#define TRACE_SCSI_ARGS 0x00000800
#define TRACE_SCSI_ALL (TRACE_SCSI_DEBUG|TRACE_SCSI_CMD|TRACE_SCSI_DATA|TRACE_SCSI_ARGS)
#define TRACE_DEBUG 0x00001000
#define TRACE_HASH 0x00002000
#define TRACE_SYNC 0x00004000
#define TRACE_QUEUE 0x00008000
#define TRACE_WARN 0x00010000
#define TRACE_MEM 0x00020000
#define TRACE_OSD 0x00040000
#define TRACE_OSDFS 0x00080000
#define TRACE_OSDSO 0x00100000
#define TRACE_ALL 0xffffffff
/*
* Set debugging level here. Turn on debugging in Makefile.
*/
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN uint32_t iscsi_debug_level;
void set_debug(const char *);
/*
* Debugging Functions
*/
#ifdef CONFIG_ISCSI_DEBUG
#define TRACE(trace, args...) do { \
if (iscsi_debug_level & trace) { \
char _iscsi_trace_buf[8192]; \
(void) snprintf(_iscsi_trace_buf, sizeof(_iscsi_trace_buf), args); \
PRINT("pid %i:%s:%d: %s", \
ISCSI_GETPID, __FILE__, __LINE__, \
_iscsi_trace_buf); \
} \
} while (/* CONSTCOND */ 0)
#define PRINT_BUFF(buf, len) do { \
if (iscsi_debug_level & TRACE_NET_BUFF) { \
int _i; \
for (_i=0 ; _i < len; _i++) { \
if (_i % 4 == 0) { \
if (_i) { \
PRINT("\n"); \
} \
PRINT("%4i:", _i); \
} \
PRINT("%2x ", (uint8_t) (buf)[_i]); \
} \
if ((len + 1) % 32) { \
PRINT("\n"); \
} \
} \
} while (/* CONSTCOND */ 0)
#define TRACE_WARNING(args...) do { \
if (iscsi_debug_level & TRACE_WARN) { \
char _iscsi_trace_buf[8192]; \
(void) snprintf(_iscsi_trace_buf, sizeof(_iscsi_trace_buf), args); \
PRINT("pid %i:%s:%i: ***WARNING*** %s", \
ISCSI_GETPID, __FILE__, __LINE__, \
_iscsi_trace_buf); \
} \
} while (/* CONSTCOND */ 0)
#else
#define TRACE(trace, args...)
#define TRACE_WARNING(args...)
#define PRINT_BUFF(buf, len)
#endif
#define TRACE_ERROR(args...) do { \
char _iscsi_trace_buf[8192]; \
(void) snprintf(_iscsi_trace_buf, sizeof(_iscsi_trace_buf), args); \
PRINT("pid %i:%s:%i: ***ERROR*** %s", \
ISCSI_GETPID, __FILE__, __LINE__, \
_iscsi_trace_buf); \
syslog(LOG_ERR, "pid %d:%s:%d: ***ERROR*** %s", \
ISCSI_GETPID, __FILE__, __LINE__, \
_iscsi_trace_buf); \
} while (/* CONSTCOND */ 0)
/*
* Byte Order
*/
#ifdef HAVE_ASM_BYTEORDER_H
#include <asm/byteorder.h>
#endif
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#endif
#ifdef HAVE_MACHINE_ENDIAN_H
#include <machine/endian.h>
#endif
#define __BYTE_ORDER _BYTE_ORDER
#define __BIG_ENDIAN _BIG_ENDIAN
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
/*
#if __BYTE_ORDER == __BIG_ENDIAN
# define ISCSI_NTOHLL(x) (x)
# define ISCSI_HTONLL(x) (x)
# define ISCSI_NTOHL(x) (x)
# define ISCSI_HTONL(x) (x)
# define ISCSI_NTOHS(x) (x)
# define ISCSI_HTONS(x) (x)
#else
# define ISCSI_NTOHLL(x) bswap_64(x)
# define ISCSI_HTONLL(x) bswap_64(x)
# define ISCSI_NTOHL(x) bswap_32(x)
# define ISCSI_HTONL(x) bswap_32(x)
# define ISCSI_NTOHS(x) bswap_16(x)
# define ISCSI_HTONS(x) bswap_16(x)
#endif
#else
*/
# define ISCSI_NTOHLL(x) BE64TOH(x)
# define ISCSI_HTONLL(x) HTOBE64(x)
# define ISCSI_NTOHL(a) ntohl(a)
# define ISCSI_HTONL(a) htonl(a)
# define ISCSI_NTOHS(a) ntohs(a)
# define ISCSI_HTONS(a) htons(a)
/*
#endif .* !linux */
/*
* printf and printk
*/
#ifdef __KERNEL__
#define PRINT printk
#else
#define PRINT printf
#endif
/*
* Process ID
*/
#ifdef __KERNEL__
#define ISCSI_GETPID current->pid
#else
#define ISCSI_GETPID getpid()
#endif
/*
* Sleeping
*/
#ifdef __KERNEL__
#define ISCSI_SLEEP(N) {uint32_t future = jiffies+N*HZ; while (jiffies<future) ISCSI_SPIN;}
#else
#define ISCSI_SLEEP(N) sleep(N)
#endif
/*
* Memory
*/
void *iscsi_malloc(unsigned);
void iscsi_free(void *);
void *iscsi_malloc_atomic(unsigned);
void iscsi_free_atomic(void *);
/*
* Comparison
*/
#ifndef MIN
#define MIN(A,B) (((A)<(B))?(A):(B))
#endif
#define MIN_3(A,B,C) (((A)<(B))?(((A)<(C))?(A):(C)):(((B)<(C))?(B):(C)))
/* Spin locks */
#ifdef __KERNEL__
typedef spinlock_t
iscsi_spin_t;
#else
typedef pthread_mutex_t
iscsi_spin_t;
#endif
int iscsi_spin_init(iscsi_spin_t * );
int iscsi_spin_lock(iscsi_spin_t * );
int iscsi_spin_unlock(iscsi_spin_t * );
int iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *);
int iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *);
int iscsi_spin_destroy(iscsi_spin_t * );
/*
* End of ISCSI spin routines
*/
/*
* Tags
*/
#define ISCSI_SET_TAG(tag) do { \
iscsi_spin_lock(&g_tag_spin); \
*tag = g_tag++; \
iscsi_spin_unlock(&g_tag_spin); \
} while (/* CONSTCOND */ 0)
#define ISCSI_SET_TAG_IN_INTR(tag) do { \
uint32_t flags; \
iscsi_spin_lock_irqsave(&g_tag_spin, &flags); \
*tag = g_tag++; \
iscsi_spin_unlock_irqrestore(&g_tag_spin, &flags); \
} while (/* CONSTCOND */ 0)
/*
* Hashing
*/
typedef struct hash_t {
struct initiator_cmd_t **bucket;
int collisions;
int insertions;
int n;
iscsi_spin_t lock;
} hash_t;
int hash_init(hash_t * , int );
int hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t );
struct initiator_cmd_t *hash_remove(hash_t * , uint32_t );
int hash_destroy(hash_t * );
/*
* Queuing
*/
typedef struct iscsi_queue_t {
int head;
int tail;
int count;
void **elem;
int depth;
iscsi_spin_t lock;
} iscsi_queue_t;
int iscsi_queue_init(iscsi_queue_t * , int );
void iscsi_queue_destroy(iscsi_queue_t * );
int iscsi_queue_insert(iscsi_queue_t * , void *);
void *iscsi_queue_remove(iscsi_queue_t * );
int iscsi_queue_depth(iscsi_queue_t * );
int iscsi_queue_full(iscsi_queue_t * );
/*
* Socket Abstraction
*/
#ifdef __KERNEL__
typedef struct socket *iscsi_socket_t;
#else
typedef int iscsi_socket_t;
#endif
/* Turning off Nagle's Algorithm doesn't always seem to work, */
/* so we combine two messages into one when the second's size */
/* is less than or equal to ISCSI_SOCK_HACK_CROSSOVER. */
#define ISCSI_SOCK_HACK_CROSSOVER 1024
#define ISCSI_SOCK_CONNECT_NONBLOCK 0
#define ISCSI_SOCK_CONNECT_TIMEOUT 1
#define ISCSI_SOCK_MSG_BYTE_ALIGN 4
int iscsi_sock_create(iscsi_socket_t * );
int iscsi_sock_setsockopt(iscsi_socket_t * , int , int , void *, unsigned );
int iscsi_sock_getsockopt(iscsi_socket_t * , int , int , void *, unsigned *);
int iscsi_sock_bind(iscsi_socket_t , int );
int iscsi_sock_listen(iscsi_socket_t );
int iscsi_sock_connect(iscsi_socket_t , char *, int );
int iscsi_sock_accept(iscsi_socket_t , iscsi_socket_t * );
int iscsi_sock_shutdown(iscsi_socket_t , int );
int iscsi_sock_close(iscsi_socket_t );
int iscsi_sock_msg(iscsi_socket_t , int , unsigned , void *, int );
int iscsi_sock_send_header_and_data(iscsi_socket_t ,
void *, unsigned ,
const void *, unsigned , int );
int iscsi_sock_getsockname(iscsi_socket_t , struct sockaddr * , unsigned *);
int iscsi_sock_getpeername(iscsi_socket_t , struct sockaddr * , unsigned *);
int modify_iov(struct iovec ** , int *, uint32_t , uint32_t );
/*
* Mutexes
*/
#ifdef __KERNEL__
typedef struct semaphore iscsi_mutex_t;
#else
typedef pthread_mutex_t iscsi_mutex_t;
#endif
int iscsi_mutex_init(iscsi_mutex_t * );
int iscsi_mutex_lock(iscsi_mutex_t * );
int iscsi_mutex_unlock(iscsi_mutex_t * );
int iscsi_mutex_destroy(iscsi_mutex_t * );
#define ISCSI_LOCK(M, ELSE) do { \
if (iscsi_mutex_lock(M) != 0) { \
TRACE_ERROR("iscsi_mutex_lock() failed\n"); \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_UNLOCK(M, ELSE) do { \
if (iscsi_mutex_unlock(M) != 0) { \
TRACE_ERROR("iscsi_mutex_unlock() failed\n"); \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_MUTEX_INIT(M, ELSE) do { \
if (iscsi_mutex_init(M) != 0) { \
TRACE_ERROR("iscsi_mutex_init() failed\n"); \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_MUTEX_DESTROY(M, ELSE) do { \
if (iscsi_mutex_destroy(M) != 0) { \
TRACE_ERROR("iscsi_mutex_destroy() failed\n"); \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
/*
* Condition Variable
*/
#ifdef __KERNEL__
typedef struct semaphore iscsi_cond_t;
#else
typedef pthread_cond_t iscsi_cond_t;
#endif
int iscsi_cond_init(iscsi_cond_t * );
int iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t * );
int iscsi_cond_signal(iscsi_cond_t * );
int iscsi_cond_destroy(iscsi_cond_t * );
#define ISCSI_COND_INIT(C, ELSE) do { \
if (iscsi_cond_init(C) != 0) { \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_WAIT(C, M, ELSE) do { \
if (iscsi_cond_wait(C, M) != 0) { \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_SIGNAL(C, ELSE) do { \
if (iscsi_cond_signal(C) != 0) { \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
#define ISCSI_COND_DESTROY(C, ELSE) do { \
if (iscsi_cond_destroy(C) != 0) { \
ELSE; \
} \
} while (/* CONSTCOND */ 0)
/*
* Threading Routines
*/
typedef struct iscsi_thread_t {
#ifdef __KERNEL__
struct task_struct *pthread;
#else
pthread_t pthread;
#endif
} iscsi_thread_t;
int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *);
#ifdef __KERNEL__
#define ISCSI_SET_THREAD(ME) me->thread.pthread = current;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
#define REPARENT_TO_INIT() reparent_to_init()
#define ISCSI_THREAD_START(NAME) \
lock_kernel(); \
daemonize(); \
REPARENT_TO_INIT(); \
unlock_kernel(); \
sprintf(current->comm, "%s", NAME);
#else
#define REPARENT_TO_INIT
#define ISCSI_THREAD_START(NAME) \
sprintf(current->comm, "%s", NAME);
#endif
#else
#define ISCSI_SET_THREAD(ME) /* for user pthread id set by pthread_create
* in iscsi_thread_create */
#define ISCSI_THREAD_START(NAME)
#endif
/*
* Worker Thread
*/
#define ISCSI_WORKER_STATE_STARTED 1
#define ISCSI_WORKER_STATE_ERROR 2
#define ISCSI_WORKER_STATE_EXITING 4
typedef struct {
iscsi_thread_t thread;
iscsi_mutex_t work_mutex;
iscsi_cond_t work_cond;
iscsi_mutex_t exit_mutex;
iscsi_cond_t exit_cond;
int id;
int pid;
volatile uint32_t state;
} iscsi_worker_t;
#define ISCSI_WORKER_EXIT(ME) do { \
TRACE(TRACE_ISCSI_DEBUG ,"exiting\n"); \
(ME)->state |= ISCSI_WORKER_STATE_EXITING; \
return 0; \
} while (/* CONSTCOND */ 0)
/*
* Spin Lock
*/
#ifdef __KERNEL__
#define ISCSI_SPIN schedule()
#else
#define ISCSI_SPIN
#endif
/*
* Pre/Post condition checking
*/
#define NO_CLEANUP {}
#define RETURN_GREATER(NAME, V1, V2, CU, RC) \
if ((V1)>(V2)) { \
TRACE_ERROR("Bad \"%s\": %u > %u.\n", NAME, V1, V2); \
CU; \
return RC; \
}
#define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC) \
if ((V1)!=(V2)) { \
TRACE_ERROR("Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
CU; \
return RC; \
}
#define WARN_NOT_EQUAL(NAME, V1, V2) \
if ((V1)!=(V2)) { \
TRACE_WARNING("Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
}
#define RETURN_EQUAL(NAME, V1, V2, CU, RC) \
if ((V1)==(V2)) { \
TRACE_ERROR("Bad \"%s\": %u == %u.\n", NAME, V1, V2); \
CU; \
return RC; \
}
/*
* Misc. Functions
*/
uint32_t iscsi_atoi(char *);
int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t );
int HexDataToText(uint8_t *, uint32_t , char *, uint32_t );
void GenRandomData(uint8_t *, uint32_t );
/* this is the maximum number of iovecs which we can use in iscsi_sock_send_header_and_data */
#ifndef ISCSI_MAX_IOVECS
#define ISCSI_MAX_IOVECS 32
#endif
enum {
/* used in iscsi_sock_msg() */
Receive = 0,
Transmit = 1
};
#endif /* _UTIL_H_ */

160
dist/iscsi/src/Makefile.in vendored Normal file
View File

@ -0,0 +1,160 @@
#
# Compiler Flags. Warning: -O causes problems w/ pthread
#
SHELL= /bin/sh
srcdir=@srcdir@
VPATH=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
BINDIR=$(exec_prefix)/bin
LIBDIR=$(exec_prefix)/lib
INCDIR=$(prefix)/include
MANDIR=$(prefix)/man
CC= @CC@
PTHREAD_FLAGS= -pthread
PTHREAD_LDFLAGS= -pthread
PTHREAD_LIBS= -lpthread
GCC_CFLAGS= -Wall -Wstrict-prototypes -fno-strict-aliasing -fno-common -Wno-trigraphs
COMMON_CFLAGS += -DCONFIG_ISCSI_DEBUG -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
CFLAGS= @CFLAGS@ ${GCC_CFLAGS} ${COMMON_CFLAGS} -I${INCLUDE} ${PTHREAD_FLAGS}
INSTALL= @INSTALL@
PREFIX= @prefix@
INCLUDE = ../include
BIN = ../bin
#CFLAGS_KERN = $(CFLAGS) -D__KERNEL__ -I/usr/src/linux-2.4.19/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -g -U__i386__ -Ui386 -DUM_FASTCALL -D__arch_um__ -DSUBARCH="i386" -D_LARGEFILE64_SOURCE -I/usr/src/linux-2.4.19/arch/um/include -Derrno=kernel_errno -DMODULE -nostdinc -I /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include -I$(SRC)/drivers/scsi -I/usr/include
CFLAGS_KERN = $(CFLAGS) -D__KERNEL__ -DMODULE -I$(SRC)/include -I$(SRC)/drivers/scsi
#ifeq ($(shell grep 'define CONFIG_MODVERSIONS' $(SRC)/include/linux/autoconf.h | wc -l | sed 's/ //g'),1)
#CFLAGS_KERN += -DMODVERSIONS -include $(SRC)/include/linux/modversions.h
#endif
#
# Compilation Targets
#
TARGETS_OSD = uosd
TARGETS = $(BIN) $(BIN)/iscsi-target $(BIN)/utest $(BIN)/usocktest $(BIN)/ktest $(BIN)/uosd
#ifeq ($(shell grep 'define CONFIG_SMP' $(SRC)/include/linux/autoconf.h | wc -l | sed 's/ //g'),1)
#TARGETS_OSD = no_smp.o
#TARGETS = no_smp.o
#else
#TARGETS_OSD += intel_iscsi.o kramdisk.o osdfs.o so.o
#TARGETS += intel_iscsi.o kramdisk.o
#endif
all: $(TARGETS)
osd: $(TARGETS_OSD)
touch osd
$(BIN):
-mkdir $(BIN)
asm:
$(CC) -Wa,-ahls,-L, $(CFLAGS_KERN) driver.c
#
# Filesystems
#
osdfs.o: $(INCLUDE)/iscsi.h iscsi.c $(INCLUDE)/initiator.h initiator.c $(INCLUDE)/util.h util.c $(INCLUDE)/parameters.h parameters.c osdfs.c $(INCLUDE)/osd.h osd_ops.c $(INCLUDE)/osd_ops.h
$(CC) $(CFLAGS_KERN) -c osdfs.c -o $(BIN)/osdfs.o
#
# SCSI Upper layer
#
so.o: so.c $(INCLUDE)/so.h $(INCLUDE)/util.h $(INCLUDE)/osd.h
$(CC) $(CFLAGS_KERN) -c so.c -o $(BIN)/so.o
#
# Initiators
#
intel_iscsi.o: $(INCLUDE)/driver.h driver.c $(INCLUDE)/iscsi.h iscsi.c $(INCLUDE)/tests.h tests.c $(INCLUDE)/initiator.h initiator.c $(INCLUDE)/util.h util.c $(INCLUDE)/parameters.h parameters.c $(INCLUDE)/osd.h $(INCLUDE)/osd_ops.h osd_ops.c
$(CC) $(CFLAGS_KERN) -c driver.c -o intel_iscsi.o
#
# User-level Targets
#
COMPATOBJS= strlcpy.o snprintf.o strtoll.o
USER_TARGET_OBJS = target.o iscsi.o util.o parameters.o ${COMPATOBJS}
$(BIN)/uosd: osd-target.c osd.c $(USER_TARGET_OBJS)
$(CC) $(CFLAGS) osd-target.c osd.c $(USER_TARGET_OBJS) ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o $(BIN)/uosd
$(BIN)/iscsi-target: iscsi-target.c disk.c $(USER_TARGET_OBJS)
$(CC) $(CFLAGS) iscsi-target.c disk.c $(USER_TARGET_OBJS) ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o $(BIN)/iscsi-target
iscsi-target: iscsi-target.c disk.c $(USER_TARGET_OBJS)
$(CC) $(CFLAGS) iscsi-target.c disk.c $(USER_TARGET_OBJS) ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o iscsi-target
uosd: osd-target.c osd.c $(USER_TARGET_OBJS)
$(CC) $(CFLAGS) osd-target.c osd.c $(USER_TARGET_OBJS) ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o uosd
#
# Kernel-level Targets
#
kramdisk.o: ktarget.c $(INCLUDE)/iscsi.h iscsi.c $(INCLUDE)/util.h util.c $(INCLUDE)/target.h target.c $(INCLUDE)/device.h disk.c $(INCLUDE)/parameters.h parameters.c
$(CC) $(CFLAGS_KERN) -DCONFIG_DISK_RAMDISK -c ktarget.c -o kramdisk.o
#
# Tests
#
$(BIN)/usocktest: usocktest.o util.o
$(CC) $(CFLAGS) usocktest.o util.o ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o $(BIN)/usocktest
$(BIN)/utest: utest.o tests.o iscsi.o util.o initiator.o parameters.o osd_ops.o
$(CC) utest.o tests.o iscsi.o util.o initiator.o parameters.o osd_ops.o -o $(BIN)/utest ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS}
$(BIN)/ktest: ktest.o
$(CC) $(CFLAGS) ktest.o -o $(BIN)/ktest
usocktest: usocktest.o util.o
$(CC) $(CFLAGS) usocktest.o util.o ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS} -o usocktest
utest: utest.o tests.o iscsi.o util.o initiator.o parameters.o osd_ops.o
$(CC) utest.o tests.o iscsi.o util.o initiator.o parameters.o osd_ops.o -o utest ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS}
ktest: ktest.o
$(CC) $(CFLAGS) ktest.o -o ktest
#
# Errors
#
no_smp.o:
@echo
@echo "************************************************************"
@echo "** The kernel mode drivers in this distribution do not **"
@echo "** support SMP. You will need to reconfigure your kernel. **"
@echo "************************************************************"
@echo
#
# Dependencies
#
osd_ops.o: $(INCLUDE)/util.h $(INCLUDE)/osd.h $(INCLUDE)/osd_ops.h osd_ops.c
util.o: util.c $(INCLUDE)/util.h
parameters.o: parameters.c $(INCLUDE)/parameters.h $(INCLUDE)/util.h md5.c
usocktest.o: usocktest.c $(INCLUDE)/util.h
disk.o: disk.c $(INCLUDE)/device.h $(INCLUDE)/util.h $(INCLUDE)/iscsi.h
osd.o: osd.c $(INCLUDE)/osd.h $(INCLUDE)/device.h $(INCLUDE)/util.h $(INCLUDE)/iscsi.h
iscsi.o: iscsi.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h
utest.o: utest.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h $(INCLUDE)/osd.h $(INCLUDE)/initiator.h $(INCLUDE)/tests.h $(INCLUDE)/parameters.h $(INCLUDE)/osd_ops.h
utarget.o: utarget.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h $(INCLUDE)/target.h $(INCLUDE)/device.h
tests.o: tests.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h $(INCLUDE)/initiator.h $(INCLUDE)/tests.h
target.o: target.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h $(INCLUDE)/target.h $(INCLUDE)/parameters.h
initiator.o: initiator.c $(INCLUDE)/iscsi.h $(INCLUDE)/util.h $(INCLUDE)/initiator.h $(INCLUDE)/parameters.h
#
# Util
#
clean:
rm -f $(INITIATORS) $(BIN)/* $(TARGETS_OSD) $(TESTS) osd *.o
test: ${TARGETS}
../bin/iscsi-target & (sleep 1; ../bin/utest -n 3 -h localhost; pkill iscsi-target)
../bin/uosd & (sleep 1; ../bin/utest -n 3 -h localhost; pkill uosd)

31
dist/iscsi/src/TODO vendored Normal file
View File

@ -0,0 +1,31 @@
To do
=====
cmdline fs or fsmmap
add discovery masking
add ability to add a target in, take one out (if !busy)
Done
====
fix debug to be command-line driven
unsigned char -> uint8_t
make target guess method to use depending on size of file/device
sprintf -> snprintf
strcpy -> strlcpy
autoconf
fix lint
Implement name-based stuff - no more inet_addr stuff
split into separate targets
rc.d scripts
move to globals_t in target.c
configuration
Make it so that target can take an iqn as its address
Manual page for iscsi-target
manual page for targets config file
get rid of hardcoded CHAP stuff
use syslog to log info
use syslog to log errors
fix memory leak of user name
error if no config file
mmap & munmap
get port from cmd line
raid0

16
dist/iscsi/src/auths vendored Normal file
View File

@ -0,0 +1,16 @@
# $Header: /cvsroot/src/dist/iscsi/src/Attic/auths,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
# passwd file for iSCSI use
nulltest:none:
#chaptest1:chap:crysanthemum
#chaptest2:CHAP:bannister
#chaptest3:chap:Rhode Island Red
# test users - throwback
#alice:chap:alicePass
#tom:chap:tomPass
# real users
#billy.nomates:chap:officer
#iqn.1991-05.com.microsoft\:ws2:CHAP:1234567890123456

281
dist/iscsi/src/conffile.c vendored Normal file
View File

@ -0,0 +1,281 @@
/* $NetBSD: conffile.c,v 1.1.1.1 2006/02/08 18:56:19 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright © 2006 \
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: conffile.c,v 1.1.1.1 2006/02/08 18:56:19 agc Exp $");
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "conffile.h"
/* start of split routines */
/* open a file */
int
conffile_open(conffile_t *sp, const char *f, const char *mode, const char *sep, const char *comment)
{
(void) memset(sp, 0x0, sizeof(*sp));
if ((sp->fp = fopen(f, mode)) == NULL) {
(void) fprintf(stderr, "can't open `%s' `%s' (%s)\n", f, mode, strerror(errno));
return 0;
}
(void) strlcpy(sp->name, f, sizeof(sp->name));
sp->sep = sep;
sp->comment = comment;
sp->readonly = (strcmp(mode, "r") == 0);
return 1;
}
/* close a file */
void
conffile_close(conffile_t *sp)
{
(void) fclose(sp->fp);
}
/* read the next line from the file */
static char *
read_line(conffile_t *sp, ent_t *ep)
{
char *from;
if (fgets(ep->buf, sizeof(ep->buf), sp->fp) == NULL) {
return NULL;
}
sp->lineno += 1;
for (from = ep->buf ; *from && isspace((unsigned int)*from) ; from++) {
}
return from;
}
/* return 1 if this line contains no entry */
static int
iscomment(conffile_t *sp, char *from)
{
return (*from == 0x0 || *from == '\n' || strchr(sp->comment, *from) != NULL);
}
/* split the entry up into fields */
static int
split_split(conffile_t *sp, ent_t *ep, char *from)
{
char *to;
char was;
int sepseen;
int cc;
for (ep->sv.c = 0 ; *from && *from != '\n' ; ) {
for (to = from, sepseen = 0 ; *to && *to != '\n' && strchr(sp->sep, *to) == NULL ; to++) {
if (*to == '\\') {
if (*(to + 1) == '\n') {
cc = (int)(to - ep->buf);
if (fgets(&ep->buf[cc], sizeof(ep->buf) - cc, sp->fp) != NULL) {
sp->lineno += 1;
}
} else {
sepseen = 1;
to++;
}
}
}
ALLOC(char *, ep->sv.v, ep->sv.size, ep->sv.c, 14, 14, "conffile_getent", exit(EXIT_FAILURE));
ep->sv.v[ep->sv.c++] = from;
was = *to;
*to = 0x0;
if (sepseen) {
char *cp;
for (cp = from ; *cp ; cp++) {
if (strchr(sp->sep, *cp) != NULL) {
(void) strcpy(cp - 1, cp);
}
}
}
if (was == 0x0 || was == '\n') {
break;
}
for (from = to + 1 ; *from && *from != '\n' && strchr(sp->sep, *from) != NULL ; from++) {
}
}
return 1;
}
/* get the next entry */
int
conffile_getent(conffile_t *sp, ent_t *ep)
{
char *from;
for (;;) {
if ((from = read_line(sp, ep)) == NULL) {
return 0;
}
if (iscomment(sp, from)) {
continue;
}
return split_split(sp, ep, from);
}
}
/* return the line number */
int
conffile_get_lineno(conffile_t *sp)
{
return sp->lineno;
}
/* return the name */
char *
conffile_get_name(conffile_t *sp)
{
return sp->name;
}
/* return the entry based upon the contents of field `f' */
int
conffile_get_by_field(conffile_t *sp, ent_t *ep, int f, char *val)
{
while (conffile_getent(sp, ep)) {
if (ep->sv.c > f && strcmp(ep->sv.v[f], val) == 0) {
return 1;
}
}
return 0;
}
/* check that we wrote `cc' chars of `buf' to `fp' */
static int
safe_write(FILE *fp, char *buf, int cc)
{
return fwrite(buf, sizeof(char), cc, fp) == cc;
}
#if 0
/* check that we wrote the entry correctly */
static int
safe_write_ent(FILE *fp, conffile_t *sp, ent_t *ep)
{
char buf[BUFSIZ];
int cc;
int i;
for (cc = i = 0 ; i < ep->sv.c ; i++) {
cc += snprintf(&buf[cc], sizeof(buf) - cc, "%s%1.1s", ep->sv.v[i], (i == ep->sv.c - 1) ? "\n" : sp->sep);
}
return safe_write(fp, buf, cc);
}
#endif
/* report an error and clear up */
static int
report_error(int fd, char *name, const char *fmt, ...)
{
va_list vp;
va_start(vp, fmt);
(void) vfprintf(stderr, fmt, vp);
va_end(vp);
(void) close(fd);
(void) unlink(name);
return 0;
}
/* put the new entry (in place of ent[f] == val, if val is non-NULL) */
int
conffile_putent(conffile_t *sp, int f, char *val, char *newent)
{
ent_t e;
FILE *fp;
char name[MAXPATHLEN];
char *from;
int fd;
(void) strlcpy(name, "/tmp/split.XXXXXX", sizeof(name));
if ((fd = mkstemp(name)) < 0) {
(void) fprintf(stderr, "can't mkstemp `%s' (%s)\n", name, strerror(errno));
return 0;
}
fp = fdopen(fd, "w");
(void) memset(&e, 0x0, sizeof(e));
for (;;) {
if ((from = read_line(sp, &e)) == NULL) {
break;
}
if (iscomment(sp, from)) {
if (!safe_write(fp, e.buf, strlen(e.buf))) {
return report_error(fd, name, "Short write 1 to `%s' (%s)\n", name, strerror(errno));
}
}
(void) split_split(sp, &e, from);
if (val != NULL && f < e.sv.c && strcmp(val, e.sv.v[f]) == 0) {
/* replace it */
if (!safe_write(fp, newent, strlen(newent))) {
return report_error(fd, name, "Short write 2 to `%s' (%s)\n", name, strerror(errno));
}
} else {
if (!safe_write(fp, e.buf, strlen(e.buf))) {
return report_error(fd, name, "Short write 3 to `%s' (%s)\n", name, strerror(errno));
}
}
}
if (val == NULL && !safe_write(fp, newent, strlen(newent))) {
return report_error(fd, name, "Short write 4 to `%s' (%s)\n", name, strerror(errno));
}
(void) close(fd);
if (rename(name, sp->name) < 0) {
return report_error(fd, name, "can't rename %s to %s (%s)\n", name, sp->name, strerror(errno));
}
return 1;
}
/* print the entry on stdout */
void
conffile_printent(ent_t *ep)
{
int i;
for (i = 0 ; i < ep->sv.c ; i++) {
printf("(%d `%s') ", i, ep->sv.v[i]);
}
printf("\n");
}

5052
dist/iscsi/src/configure vendored Executable file

File diff suppressed because it is too large Load Diff

26
dist/iscsi/src/configure.ac vendored Normal file
View File

@ -0,0 +1,26 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(iscsi.c)
AC_CONFIG_HEADER(../include/config.h)
dnl Checks for programs.
AC_PROG_INSTALL
AC_PROG_CC
AC_PROG_RANLIB
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/types.h sys/param.h sys/stat.h sys/time.h sys/mman.h sys/uio.h sys/socket.h sys/time.h sys/vfs.h)
AC_CHECK_HEADERS(arpa/inet.h netinet/in.h netinet/tcp.h netdb.h)
AC_CHECK_HEADERS(asm/byteorder.h byteswap.h machine/endian.h)
AC_CHECK_HEADERS(ctype.h errno.h fcntl.h pthread.h pwd.h signal.h stdlib.h syslog.h unistd.h string.h stdarg.h utime.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AC_CHECK_TYPES([long long, unsigned long long])
dnl Check for functionality
AC_CHECK_FUNCS(asprintf asnprintf bswap64 snprintf strlcpy strtoll daemon vasprintf vasnprintf vsnprintf)
dnl that's it for now...
AC_OUTPUT(Makefile)

1157
dist/iscsi/src/disk.c vendored Normal file

File diff suppressed because it is too large Load Diff

652
dist/iscsi/src/driver.c vendored Normal file
View File

@ -0,0 +1,652 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Intel SCSI device driver for iSCSI
*/
#ifdef __linux__
#include <linux/blk.h>
#include <linux/string.h>
#include <scsi.h>
#include <hosts.h>
#include <sd.h>
#endif
#include "util.h"
#include "util.c"
#include "driver.h"
#include "iscsi.h"
#include "iscsi.c"
#include "tests.h"
#include "tests.c"
#include "osd_ops.h"
#include "osd_ops.c"
#include "parameters.h"
#include "parameters.c"
#include "initiator.h"
#include "initiator.c"
/*
* Version-specific include files
*/
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
#include <linux/in.h>
#else
struct proc_dir_entry iscsi_proc_dir = {PROC_SCSI_NOT_PRESENT, 5, "iscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2};
#endif
#ifdef MODULE
Scsi_Host_Template driver_template = ISCSI;
#include "scsi_module.c"
#endif
/*
* Globals
*/
static initiator_cmd_t *g_cmd;
static iscsi_queue_t g_cmd_q;
static struct iovec **g_iov;
static iscsi_queue_t g_iovec_q;
static iscsi_driver_stats_t g_stats;
/*
* Definitions
*/
/*
* Starting with kernel 2.4.10, we define a license string. This source is under BSD License.
* Consult <linux/include/linux/module.h> for details
*/
MODULE_AUTHOR("Intel Corporation, <http://www.intel.com>");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
MODULE_LICENSE("Dual BSD/GPL"); /* This source is under BSD License. This is the closest ident that module.h provides */
# endif
/*
* Private
*/
static int driver_init(void) {
int i;
TRACE(TRACE_SCSI_DEBUG, "initializing iSCSI driver\n");
if ((g_cmd=iscsi_malloc_atomic(sizeof(initiator_cmd_t)*CONFIG_INITIATOR_QUEUE_DEPTH))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
return -1;
}
if ((g_iov=iscsi_malloc_atomic(sizeof(struct iovec*)*CONFIG_INITIATOR_QUEUE_DEPTH))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
iscsi_free_atomic(g_cmd);
return -1;
}
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) {
g_iov[i] = NULL;
g_cmd[i].ptr = NULL;
}
#define DI_ERROR { \
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) { \
if (g_cmd[i].ptr != NULL) iscsi_free_atomic(g_cmd[i].ptr); \
} \
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) { \
if (g_iov[i] != NULL) iscsi_free_atomic(g_iov[i]); \
} \
iscsi_free_atomic(g_iov); \
iscsi_free_atomic(g_cmd); \
return -1; \
}
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) {
if ((g_iov[i]=iscsi_malloc_atomic(sizeof(struct iovec)*SG_ALL))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
DI_ERROR;
}
}
if (iscsi_queue_init(&g_cmd_q, CONFIG_INITIATOR_QUEUE_DEPTH)!=0) {
TRACE_ERROR("iscsi_queue_init() failed\n");
DI_ERROR;
}
if (iscsi_queue_init(&g_iovec_q, CONFIG_INITIATOR_QUEUE_DEPTH)!=0) {
TRACE_ERROR("iscsi_queue_init() failed\n");
DI_ERROR;
}
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) {
if ((g_cmd[i].ptr = iscsi_malloc_atomic(sizeof(iscsi_scsi_cmd_args_t)))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
DI_ERROR;
}
g_cmd[i].type = ISCSI_SCSI_CMD;
if (iscsi_queue_insert(&g_cmd_q, &g_cmd[i])!=0) {
TRACE_ERROR("iscsi_queue_insert() failed\n");
DI_ERROR;
}
if (iscsi_queue_insert(&g_iovec_q, g_iov[i])!=0) {
TRACE_ERROR("iscsi_queue_insert() failed\n");
DI_ERROR;
}
}
memset(&g_stats, 0, sizeof(g_stats));
iscsi_spin_init(&g_stats.lock);
if (initiator_init()!=0) {
TRACE_ERROR("initiator_init() failed\n");
DI_ERROR;
}
TRACE(TRACE_SCSI_DEBUG, "iSCSI initialization complete\n");
return 0;
}
static int driver_shutdown(void) {
int i;
TRACE(TRACE_SCSI_DEBUG, "shutting down iSCSI driver\n");
if (initiator_shutdown()!=0) {
TRACE_ERROR("initiator_shutdown() failed\n");
return -1;
}
iscsi_spin_destroy(&g_stats.lock);
iscsi_queue_destroy(&g_iovec_q);
iscsi_queue_destroy(&g_cmd_q);
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) {
iscsi_free_atomic(g_iov[i]);
iscsi_free_atomic(g_cmd[i].ptr);
}
iscsi_free_atomic(g_cmd);
iscsi_free_atomic(g_iov);
TRACE(TRACE_SCSI_DEBUG, "iSCSI driver shutdown complete\n");
return 0;
}
/*
* Public
*/
int iscsi_detect(Scsi_Host_Template *tptr) {
struct Scsi_Host *ptr;
TRACE(TRACE_SCSI_DEBUG, "detecting iSCSI host\n");
spin_unlock(&io_request_lock);
if (driver_init()!=0) {
TRACE_ERROR("driver_init() failed\n");
spin_lock(&io_request_lock);
return 0; /*No 'SCSI' host detected, return 0 */
}
ptr = scsi_register(tptr, 0);
ptr->max_id = CONFIG_INITIATOR_NUM_TARGETS;
ptr->max_lun = CONFIG_DRIVER_MAX_LUNS;
ptr->max_cmd_len = 255;
TRACE(TRACE_SCSI_DEBUG, "iSCSI host detected\n");
spin_lock(&io_request_lock);
return 1;
}
int iscsi_release(struct Scsi_Host *host) {
TRACE(TRACE_SCSI_DEBUG, "releasing iSCSI host\n");
driver_shutdown();
TRACE(TRACE_SCSI_DEBUG, "iSCSI host released\n");
return 0;
}
int iscsi_bios_param(Disk *disk, kdev_t dev, int *ip) {
ip[0] = 32; /* heads */
ip[1] = 63; /* sectors */
if((ip[2] = disk->capacity >> 11) > 1024) { /* cylinders, test for big disk */
ip[0] = 255; /* heads */
ip[1] = 63; /* sectors */
ip[2] = disk->capacity / (255 * 63); /* cylinders */
}
TRACE(TRACE_SCSI_DEBUG, "%u sectors, H/S/C: %u/%u/%u\n", disk->capacity, ip[0], ip[1], ip[2]);
return 0;
}
int iscsi_command(Scsi_Cmnd *SCpnt) {
TRACE(TRACE_SCSI_DEBUG, "0x%p: op 0x%x, chan %i, target %i, lun %i, bufflen %i, sg %i\n",
SCpnt, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun,
SCpnt->request_bufflen, SCpnt->use_sg);
TRACE_ERROR("NOT IMPLEMENTED\n");
return -1;
}
int iscsi_done(void *ptr) {
initiator_cmd_t *cmd = (initiator_cmd_t *) ptr;
iscsi_scsi_cmd_args_t *scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr;
Scsi_Cmnd *SCpnt = (Scsi_Cmnd *) cmd->callback_arg;
unsigned long flags = 0;
if (SCpnt==0) {
return 0;
}
if (cmd->status==0) {
SCpnt->result = scsi_cmd->status;
} else {
SCpnt->result = -1;
}
TRACE(TRACE_SCSI_DEBUG, "scsi_arg 0x%p SCpnt 0x%p op 0x%x done (result %i)\n",
scsi_cmd, SCpnt, SCpnt->cmnd[0], SCpnt->result);
if ((scsi_cmd->input)&&(scsi_cmd->output)) {
TRACE_ERROR("bidi xfers not implemented\n");
return -1;
} else if (scsi_cmd->input) {
iscsi_spin_lock_irqsave(&g_stats.lock, &flags);
if ((g_stats.rx+SCpnt->request_bufflen)<g_stats.rx) {
g_stats.rx_overflow++;
}
g_stats.rx += SCpnt->request_bufflen;
g_stats.rx_queued -= SCpnt->request_bufflen;
if (g_stats.num_rx_queued) g_stats.num_rx_queued--;
g_stats.num_rx++;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
} else if (scsi_cmd->output) {
iscsi_spin_lock_irqsave(&g_stats.lock, &flags);
if ((g_stats.tx+SCpnt->request_bufflen)<g_stats.tx) {
g_stats.tx_overflow++;
}
g_stats.tx += SCpnt->request_bufflen;
g_stats.tx_queued -= SCpnt->request_bufflen;
if (g_stats.num_tx_queued) g_stats.num_tx_queued--;
g_stats.num_tx++;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
}
if (SCpnt->host_scribble) {
unsigned char *hs;
hs = SCpnt->host_scribble;
SCpnt->host_scribble = NULL; /* for abort */
if (iscsi_queue_insert(&g_iovec_q, hs)!=0) {
TRACE_ERROR("iscsi_queue_insert() failed\n");
return -1;
}
}
iscsi_free_atomic(scsi_cmd->ahs);
if (iscsi_queue_insert(&g_cmd_q, cmd)!=0) {
TRACE_ERROR("iscsi_queue_insert() failed\n");
cmd->callback_arg = NULL; /* for abort */
return -1;
}
cmd->callback_arg = NULL; /* for abort */
if (SCpnt->result==0) {
SCpnt->scsi_done(SCpnt);
} else {
TRACE_ERROR("SCSI cmd 0x%x failed at iSCSI level (ignoring)\n", SCpnt->cmnd[0]);
}
return 0;
}
int iscsi_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
initiator_cmd_t *cmd;
iscsi_scsi_cmd_args_t *scsi_cmd;
unsigned char *data;
unsigned length, trans_len;
int input, output;
unsigned long flags =0;
/* Tagged command queuing is handled from within this SCSI driver. */
if ((SCpnt->device->tagged_supported)&&(SCpnt->device->tagged_queue)) {
SCpnt->tag = SCpnt->device->current_tag++;
}
spin_unlock(&io_request_lock);
TRACE(TRACE_SCSI_DEBUG, "SCpnt %p: tid %i lun %i op 0x%x tag %u len %i sg %i buff 0x%p\n",
SCpnt, SCpnt->target, SCpnt->lun, SCpnt->cmnd[0], SCpnt->tag, SCpnt->request_bufflen,
SCpnt->use_sg, SCpnt->buffer);
/* Determine direction of data transfer */
trans_len = length = output = input = 0;
if ((SCpnt->cmnd[0]!=TEST_UNIT_READY)&&(SCpnt->request_bufflen)) {
if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
output = 1; input = 0;
length = trans_len = SCpnt->request_bufflen;
iscsi_spin_lock_irqsave(&g_stats.lock, &flags);
g_stats.num_tx_queued++;
g_stats.tx_queued += trans_len;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
} else if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
length = output = 0; input = 1;
trans_len = SCpnt->request_bufflen;
iscsi_spin_lock_irqsave(&g_stats.lock, &flags);
g_stats.num_rx_queued++;
g_stats.rx_queued += trans_len;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
}
}
/* Convert scatterlist to iovec */
if (SCpnt->use_sg) {
struct scatterlist *sg = (struct scatterlist *) SCpnt->buffer;
struct iovec *iov;
int i;
iov = iscsi_queue_remove(&g_iovec_q);
if (iov == NULL) {
TRACE_ERROR("iscsi_queue_remove() failed\n");
spin_lock(&io_request_lock);
return -1;
}
for (i=0; i<SCpnt->use_sg; i++) {
iov[i].iov_base = sg[i].address;
iov[i].iov_len = sg[i].length;
}
data = SCpnt->host_scribble = (unsigned char *)iov;
} else {
data = SCpnt->buffer;
SCpnt->host_scribble = NULL;
}
/* Get free cmd structure */
if ((cmd=iscsi_queue_remove(&g_cmd_q))==NULL) {
TRACE_ERROR("iscsi_queue_remove() failed\n");
spin_lock(&io_request_lock);
return -1;
}
scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr;
memset(scsi_cmd, 0, sizeof(*scsi_cmd));
scsi_cmd->send_data = output?data:0;
scsi_cmd->send_sg_len = output?SCpnt->use_sg:0;
scsi_cmd->recv_data = input?data:NULL;
scsi_cmd->recv_sg_len = input?SCpnt->use_sg:0;
scsi_cmd->input = input;
scsi_cmd->output = output;
scsi_cmd->length = length;
scsi_cmd->lun = SCpnt->lun;
scsi_cmd->lun = scsi_cmd->lun << 32;
scsi_cmd->trans_len = trans_len;
scsi_cmd->cdb = SCpnt->cmnd;
/* AHS for CDBs larget than 16 bytes */
if (SCpnt->cmd_len>16) {
TRACE(TRACE_ISCSI_DEBUG, "creating AHS for extended CDB (%i bytes)\n", SCpnt->cmd_len);
if ((scsi_cmd->ahs=iscsi_malloc_atomic(SCpnt->cmd_len-16))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
spin_lock(&io_request_lock);
return -1;
}
memset(scsi_cmd->ahs, 0, 4);
*((uint16_t *)scsi_cmd->ahs) = HTONS(SCpnt->cmd_len-15); /* AHS length */
scsi_cmd->ahs[2] = 0x01; /* Type */
memcpy(scsi_cmd->ahs+4, SCpnt->cmnd+16, SCpnt->cmd_len-16); /* Copy in remaining CDB */
scsi_cmd->ahs_len = SCpnt->cmd_len-16;
}
SCpnt->scsi_done = done; /* The midlayer's callback called in iscsi_done */
SCpnt->result = 0x02; /* Default to a check condition */
cmd->callback = iscsi_done; /* This driver's callback called by initiator library */
cmd->callback_arg = SCpnt;
cmd->isid = SCpnt->target;
if (initiator_enqueue(cmd)!=0) {
TRACE_ERROR("initiator_enqueue() failed\n");
if (SCpnt->cmd_len>16) iscsi_free_atomic(scsi_cmd->ahs);
spin_lock(&io_request_lock);
return -1;
}
spin_lock(&io_request_lock);
return 0;
}
int iscsi_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int writing) {
unsigned char *info = NULL;
uint32_t infolen = 8192;
int len = 0;
TRACE(TRACE_SCSI_DEBUG, "buffer = 0x%p, offset %u, length = %i, hostno %i, writing %i\n",
buffer, (unsigned) offset, length, hostno, writing);
/* writing resets counters */
if (writing) {
iscsi_spin_lock(&g_stats.lock);
g_stats.num_tx = g_stats.num_tx_queued = 0;
g_stats.num_rx = g_stats.num_rx_queued = 0;
g_stats.tx_queued = g_stats.tx = g_stats.tx_overflow = g_stats.tx_error = 0;
g_stats.rx_queued = g_stats.rx = g_stats.rx_overflow = g_stats.rx_error = 0;
g_stats.aborts_success = g_stats.aborts_failed = 0;
g_stats.device_resets = g_stats.bus_resets = g_stats.host_resets = 0;
iscsi_spin_unlock(&g_stats.lock);
return 0;
} else {
if ((info=iscsi_malloc_atomic(infolen))==NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
return -1;
}
len += snprintf(info, infolen, "%s\n\n", driver_template.name);
len += snprintf(&info[len], infolen - len, "Write file to reset counters (e.g., \"echo reset > /proc/scsi/iscsi/2\").\n\n");
len += snprintf(&info[len], infolen - len, "--------------------\n");
len += snprintf(&info[len], infolen - len, "Driver Configuration\n");
len += snprintf(&info[len], infolen - len, "--------------------\n\n");
len += snprintf(&info[len], infolen - len, " CONFIG_INITIATOR_NUM_TARGETS: %u\n", CONFIG_INITIATOR_NUM_TARGETS);
len += snprintf(&info[len], infolen - len, " CONFIG_INITIATOR_QUEUE_DEPTH: %u\n\n", CONFIG_INITIATOR_QUEUE_DEPTH);
len += snprintf(&info[len], infolen - len, "---------------\n");
len += snprintf(&info[len], infolen - len, "SCSI Statistics\n");
len += snprintf(&info[len], infolen - len, "---------------\n\n");
len += snprintf(&info[len], infolen - len, " Tx:\n");
len += snprintf(&info[len], infolen - len, " queued: %u\n", g_stats.num_tx_queued);
len += snprintf(&info[len], infolen - len, " completed: %u\n", g_stats.num_tx);
len += snprintf(&info[len], infolen - len, " avg size: %u\n", g_stats.num_tx?(g_stats.tx/g_stats.num_tx):0);
len += snprintf(&info[len], infolen - len, " total bytes: %u MB\n", g_stats.tx/1048576 + g_stats.tx_overflow*4096);
len += snprintf(&info[len], infolen - len, " total overflow: %u\n", g_stats.tx_overflow);
len += snprintf(&info[len], infolen - len, " Rx:\n");
len += snprintf(&info[len], infolen - len, " queued: %u\n", g_stats.num_rx_queued);
len += snprintf(&info[len], infolen - len, " completed: %u\n", g_stats.num_rx);
len += snprintf(&info[len], infolen - len, " avg size: %u\n", g_stats.num_rx?(g_stats.rx/g_stats.num_rx):0);
len += snprintf(&info[len], infolen - len, " total bytes: %u MB\n", g_stats.rx/1048576 + g_stats.rx_overflow*4096);
len += snprintf(&info[len], infolen - len, " total overflow: %u\n", g_stats.rx_overflow);
len += snprintf(&info[len], infolen - len, " Errors:\n");
len += snprintf(&info[len], infolen - len, " aborts: %u\n", g_stats.aborts_success);
/* len += snprintf(&info[len], infolen - len, " failed aborts: %u\n", g_stats.aborts_failed); */
len += snprintf(&info[len], infolen - len, " device resets: %u\n", g_stats.device_resets);
len += snprintf(&info[len], infolen - len, " bus resets: %u\n", g_stats.bus_resets);
len += snprintf(&info[len], infolen - len, " host resets: %u\n", g_stats.host_resets);
len += snprintf(&info[len], infolen - len, " Tx error bytes: %u\n", g_stats.tx_error);
len += snprintf(&info[len], infolen - len, " Rx error bytes: %u\n\n", g_stats.rx_error);
len += snprintf(&info[len], infolen - len, "--------------------\n");
len += snprintf(&info[len], infolen - len, "iSCSI Initiator Info\n");
len += snprintf(&info[len], infolen - len, "--------------------\n\n");
if ((len += initiator_info(&info[len], infolen, len))==-1) {
TRACE_ERROR("initiator_info() failed\n");
if (info != NULL) iscsi_free_atomic(info);
return -1;
}
if (offset>len-1) {
len = 0;
} else if (offset+length>len-1) {
len -= offset;
} else {
len = length;
}
*start = buffer;
memcpy(buffer, info+offset, len);
if (info != NULL) iscsi_free_atomic(info);
return len;
}
}
int iscsi_ioctl (Scsi_Device *dev, int cmd, void *argp) {
int i;
int lun = 0;
/* Run tests for each target */
for (i=0; i<CONFIG_INITIATOR_NUM_TARGETS; i++) {
if (test_all(i, lun)!=0) {
TRACE_ERROR("test_all() failed\n");
return -1;
}
}
return 0;
}
void iscsi_select_queue_depths(struct Scsi_Host *host, Scsi_Device *scsi_devs) {
struct scsi_device *device;
for (device = scsi_devs; device; device = device->next) {
if (device->host != host) {
TRACE_ERROR("got device for different host\n");
continue;
}
if (device->tagged_supported) {
TRACE(TRACE_SCSI_DEBUG, "target %i lun %i supports TCQ\n", device->id, device->lun);
device->tagged_queue = 1;
device->current_tag = 0;
device->queue_depth = CONFIG_INITIATOR_QUEUE_DEPTH;
TRACE(TRACE_SCSI_DEBUG, "device queue depth set to %i\n", device->queue_depth);
} else {
TRACE(TRACE_SCSI_DEBUG, "target %i lun %i does NOT support TCQ\n", device->id, device->lun);
device->queue_depth = 1;
}
}
}
/*
* Error Handling Routines
*/
int iscsi_abort_handler (Scsi_Cmnd *SCpnt) {
iscsi_scsi_cmd_args_t *scsi_cmd;
initiator_session_t *sess;
int i;
unsigned long flags;
spin_unlock_irq(&io_request_lock);
TRACE_ERROR("aborting SCSI cmd 0x%p (op 0x%x, tid %i, lun %i)\n",
SCpnt, SCpnt->cmnd[0], SCpnt->target, SCpnt->lun);
for (i=0; i<CONFIG_INITIATOR_QUEUE_DEPTH; i++) {
/* Find the cmd ptr in g_cmd. We look for the callback_arg that's equal */
/* to SCpnt. iscsi_done() sets callback_arg to NULL when a command */
/* completes. So we know that any non_NULL callback_arg is associated */
/* with an outstanding command. */
if (g_cmd[i].callback_arg == SCpnt) {
/* Abort the command */
if (initiator_abort(&g_cmd[i])!=0) {
TRACE_ERROR("initiator_abort() failed\n");
spin_lock_irq(&io_request_lock);
return FAILED;
}
/* Update counters */
scsi_cmd = (iscsi_scsi_cmd_args_t *) g_cmd[i].ptr;
if ((scsi_cmd->input)&&(scsi_cmd->output)) {
TRACE_ERROR("bidi xfers not implemented\n");
spin_lock_irq(&io_request_lock);
return FAILED;
} else if (scsi_cmd->input) {
iscsi_spin_lock_irqsave(&g_stats.lock,&flags);
g_stats.rx_error += SCpnt->request_bufflen;
g_stats.rx_queued -= SCpnt->request_bufflen;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
} else if (scsi_cmd->output) {
iscsi_spin_lock_irqsave(&g_stats.lock, &flags);
g_stats.tx_error += SCpnt->request_bufflen;
g_stats.tx_queued -= SCpnt->request_bufflen;
iscsi_spin_unlock_irqrestore(&g_stats.lock, &flags);
}
break;
}
}
/* Destroy session */
if (g_target[SCpnt->target].has_session) {
sess = g_target[SCpnt->target].sess;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
if (in_interrupt()) {
TRACE_ERROR("aborting within interrupt (killing Tx and Rx threads)\n");
#endif
TRACE_ERROR("killing Tx and Rx threads\n");
kill_proc(sess->rx_worker.pid, SIGKILL, 1);
kill_proc(sess->tx_worker.pid, SIGKILL, 1);
sess->tx_worker.state = 0;
sess->rx_worker.state = 0;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
} else {
TRACE_ERROR("aborting outside interrupt (gracefully ending Tx and Rx)\n");
}
#endif
TRACE(TRACE_ISCSI_DEBUG, "destroying session\n");
if (session_destroy_i(sess)!=0) {
TRACE_ERROR("session_destroy() failed\n");
g_stats.aborts_failed++;
spin_lock_irq(&io_request_lock);
return FAILED;
}
} else {
TRACE(TRACE_ISCSI_DEBUG, "no session\n");
}
g_stats.aborts_success++;
TRACE_ERROR("successfully aborted SCSI cmd 0x%p (op 0x%x, tid %i, lun %i)\n",
SCpnt, SCpnt->cmnd[0], SCpnt->target, SCpnt->lun);
spin_lock_irq(&io_request_lock);
return SUCCESS;
}
int iscsi_device_reset_handler (Scsi_Cmnd *SCpnt) {
TRACE_ERROR("***********************\n");
TRACE_ERROR("*** DEVICE %i RESET ***\n", SCpnt->target);
TRACE_ERROR("***********************\n");
g_stats.device_resets++;
return SUCCESS;
}
int iscsi_bus_reset_handler (Scsi_Cmnd *SCpnt) {
TRACE_ERROR("********************\n");
TRACE_ERROR("*** BUS %i RESET ***\n", SCpnt->target);
TRACE_ERROR("********************\n");
g_stats.bus_resets++;
return SUCCESS;
}
int iscsi_host_reset_handler(Scsi_Cmnd *SCpnt) {
TRACE_ERROR("*********************\n");
TRACE_ERROR("*** HOST RESET %i ***\n", SCpnt->target);
TRACE_ERROR("*********************\n");
g_stats.host_resets++;
return SUCCESS;
}

17
dist/iscsi/src/etc/auths vendored Normal file
View File

@ -0,0 +1,17 @@
# $NetBSD: auths,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
# test passwd file for iSCSI use
nulltest:none:
#chaptest1:chap:crysanthemum
#chaptest2:CHAP:bannister
#chaptest3:chap:Rhode Island Red
# test users - throwback
#alice:chap:alicePass
#tom:chap:tomPass
# real users
#billy.nomates:chap:officer
#iqn.1991-05.com.microsoft\:ws2:CHAP:1234567890123456

12
dist/iscsi/src/etc/passwd vendored Normal file
View File

@ -0,0 +1,12 @@
# $Header: /cvsroot/src/dist/iscsi/src/etc/Attic/passwd,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
# test passwd file for iSCSI use
nulltest:none:
chaptest1:chap:crysanthemum
chaptest2:CHAP:bannister
chaptest3:chap:Rhode Island Red
# real users
agc:chap:officer
iqn.1991-05.com.microsoft\:ws2:CHAP:1234567890123456

18
dist/iscsi/src/etc/rc.d/iscsi_target vendored Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
#
# $NetBSD: iscsi_target,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
#
# PROVIDE: iscsi_target
# REQUIRE: NETWORKING mountall beforemountlkm quota
$_rc_subr_loaded . /etc/rc.subr
name="iscsi_target"
rcvar=$name
command="/usr/local/bin/iscsi-target"
required_files="/usr/local/etc/iscsi/targets"
pidfile="/var/run/iscsi-target.pid"
load_rc_config $name
run_rc_command "$1"

21
dist/iscsi/src/etc/targets vendored Normal file
View File

@ -0,0 +1,21 @@
# $NetBSD: targets,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
#
# Structure of this file:
#
# + an extent is a straight (offset, length) pair of a file or device
# it's the lowest common storage denominator
# at least one is needed
# + a device is made up of one or more extents or other devices
# devices can be added in a hierachical manner, to enhance resilience
# + in this example, no device definitions are necessary, as the target
# will just use a simple extent for persistent storage
# + a target is made up of 1 or more devices
# The code does not support RAID1 recovery at present
# Simple file showing 1 extent, mapped straight into 1 target
# extents
extent0 /tmp/iscsi-target0 0 100MB
# targets
target0 extent0 3260 10.4.0.0/16

20
dist/iscsi/src/examples/1.conf vendored Normal file
View File

@ -0,0 +1,20 @@
# Simple file showing 1 extent, device and target
# extent
# name storage offset (in bytes) size
extent0 /tmp/iscsi-target0 0 100MB
# devices
# name resilience devices/extents
device0 RAID0 extent0
# targets
# name device netmask
target0 device0 10.4.0.0/16
# NB, in the above, the intermediate device definition is not necessary.
# It could have been simply:
extent1 /tmp/iscsi-target1 0 100MB
target1 extent1 10.4.0.0/16

19
dist/iscsi/src/examples/2.conf vendored Normal file
View File

@ -0,0 +1,19 @@
# Complex file showing 3-way RAID1 (with RAID1 components),
# also using local and (NFS) remote components
# extents
extent0 /iscsi/extents/0 0 100MB
extent1 /imports/remote1/iscsi/extents/0 0 100MB
extent2 /iscsi/extents/1 0 100MB
extent3 /imports/remote1/iscsi/extents/1 0 100MB
extent4 /iscsi/extents/2 0 100MB
extent5 /imports/remote1/iscsi/extents/2 0 100MB
# devices
device0 RAID1 extent0 extent1
device1 RAID1 extent2 extent3
device2 RAID1 extent4 extent5
device3 RAID1 device0 device1 device2
# targets
target0 device3 10.4.0.0/16

22
dist/iscsi/src/examples/3.conf vendored Normal file
View File

@ -0,0 +1,22 @@
# Complex file showing 3-way RAID1 (with RAID1 components),
# also using local and (NFS) remote components
# extents
extent0 /iscsi/extents/0 0 100MB
extent1 /imports/remote1/iscsi/extents/0 0 100MB
extent2 /iscsi/extents/1 0 100MB
extent3 /imports/remote1/iscsi/extents/1 0 100MB
extent4 /iscsi/extents/2 0 100MB
extent5 /imports/remote1/iscsi/extents/2 0 100MB
extent6 /iscsi/extents/3 0 100MB
# devices
device0 RAID1 extent0 extent1
device1 RAID1 extent2 extent3
device2 RAID1 extent4 extent5
device3 RAID1 device0 device1 device2
device4 RAID0 extent6
# targets
target0 device3 10.4.0.0/16
target1 device4 127.0.0.0/8

23
dist/iscsi/src/examples/4.conf vendored Normal file
View File

@ -0,0 +1,23 @@
# Complex file showing 3-way RAID1 (with RAID1 components),
# also using local and (NFS) remote components
# extents
extent0 /iscsi/extents/0 0 100MB
extent1 /imports/remote1/iscsi/extents/0 0 100MB
extent2 /iscsi/extents/1 0 100MB
extent3 /imports/remote1/iscsi/extents/1 0 100MB
extent4 /iscsi/extents/2 0 100MB
extent5 /imports/remote1/iscsi/extents/2 0 100MB
extent6 /iscsi/extents/3 0 100GB
# devices
device0 RAID1 extent0 extent1
device1 RAID1 extent2 extent3
device2 RAID1 extent4 extent5
device3 RAID1 device0 device1 device2
# targets
target0 device3 10.4.0.0/16
# a target can be made from just an extent
target1 extent6 127.0.0.0/8

3187
dist/iscsi/src/initiator.c vendored Normal file

File diff suppressed because it is too large Load Diff

238
dist/iscsi/src/install-sh vendored Executable file
View File

@ -0,0 +1,238 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
tranformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

92
dist/iscsi/src/iscsi-harness.8 vendored Normal file
View File

@ -0,0 +1,92 @@
.\" $NetBSD: iscsi-harness.8,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
.\"
.\" Copyright © 2006 Alistair Crooks. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 22, 2006
.Dt ISCSI-HARNESS 8
.Os
.Sh NAME
.Nm iscsi-harness
.Nd test harness for iscsi-target
.Sh SYNOPSIS
.Nm
.Op Fl a Ar authentication type
.Op Fl d Ar digest type
.Op Fl h Ar target hostname
.Op Fl l Ar number of luns
.Op Fl n Ar number of test iterations
.Op Fl t Ar number of targets
.Op Fl u Ar user name
.Sh DESCRIPTION
.Nm
is the test harness for
.Xr iscsi-target 8 ,
the iSCSI service.
.Nm
acts as an initiator, performing a set of tests for a number of iterations.
to show network-related information,
It connects to the
.Xr iscsi-target 8
service, and performs a discovery session,
then sends data of various sizes to the target, and reads
data of various sizes from the target.
.Pp
The authentication type can be one of
.Ar chap ,
.Ar Kerberos ,
.Ar SRP ,
or
.Ar none .
The default value is
.Ar none .
.Pp
The digest type can be one of
.Ar header ,
.Ar data ,
.Ar both
or
.Ar all ,
or
.Ar none .
The default value is
.Ar none .
.Sh FILES
.Bl -tag -width /var/run/iscsi-target.pid -compact
.It Pa /etc/iscsi/targets
the list of exported storage
.It Pa /var/run/iscsi-target.pid
the PID of the currently running
.Nm
.El
.Sh SEE ALSO
.Xr targets 5 ,
.Xr iscsi-target 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 4.0 .

192
dist/iscsi/src/iscsi-harness.c vendored Normal file
View File

@ -0,0 +1,192 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define EXTERN
#include <sys/types.h>
#include <sys/param.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include "scsi_cmd_codes.h"
#include "iscsi.h"
#include "initiator.h"
#include "tests.h"
int
main(int argc, char **argv)
{
struct sigaction act;
struct passwd *pwp;
char hostname[1024];
char *host;
char *user;
int tgtlo = 0;
int tgthi = CONFIG_INITIATOR_NUM_TARGETS;
int target = -1;
int digest_type;
int mutual_auth;
int auth_type;
int lun = 0;
int i, j;
int iterations;
/* Check args */
iterations = 1;
user = NULL;
(void) gethostname(host = hostname, sizeof(hostname));
digest_type = DigestNone;
auth_type = AuthNone;
mutual_auth = 0;
while ((i = getopt(argc, argv, "a:d:h:l:n:t:u:")) != -1) {
switch(i) {
case 'a':
if (strcasecmp(optarg, "chap") == 0) {
auth_type = AuthCHAP;
} else if (strcasecmp(optarg, "kerberos") == 0) {
auth_type = AuthKerberos;
} else if (strcasecmp(optarg, "srp") == 0) {
auth_type = AuthSRP;
}
break;
case 'd':
if (strcasecmp(optarg, "header") == 0) {
digest_type = DigestHeader;
} else if (strcasecmp(optarg, "data") == 0) {
digest_type = DigestData;
} else if (strcasecmp(optarg, "both") == 0 || strcasecmp(optarg, "all") == 0) {
digest_type = (DigestHeader | DigestData);
}
break;
case 'h':
host = optarg;
break;
case 'l':
lun = atoi(optarg);
break;
case 'n':
iterations = atoi(optarg);
break;
case 't':
target = atoi(optarg);
break;
case 'u':
user = optarg;
break;
default:
(void) fprintf(stderr, "%s: unknown option `%c'", *argv, i);
}
}
if (user == NULL) {
if ((pwp = getpwuid(geteuid())) == NULL) {
TRACE_ERROR("can't find user information\n");
exit(EXIT_FAILURE);
}
user = pwp->pw_name;
}
if (target != -1) {
if (target >= CONFIG_INITIATOR_NUM_TARGETS) {
TRACE_ERROR("initiator only configured with %i targets\n", CONFIG_INITIATOR_NUM_TARGETS);
exit(EXIT_FAILURE);
}
tgtlo = target;
tgthi = target + 1;
}
if (argc == 1) {
(void) fprintf(stderr, "usage: %s [-h hostname] [-l lun] [-n iterations] [-t target]\n", *argv);
exit(EXIT_FAILURE);
}
for (j = 0; j < iterations; j++) {
PRINT("<ITERATION %i>\n", j);
/* Ignore sigpipe */
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
/* Initialize Initiator */
if (initiator_init(host, user, auth_type, mutual_auth, digest_type) == -1) {
TRACE_ERROR("initiator_init() failed\n");
return -1;
}
/* Run tests for each target */
for (i = tgtlo; i < tgthi; i++) {
if (test_all(i, lun) != 0) {
TRACE_ERROR("test_all() failed\n");
return -1;
}
}
/* Shutdown Initiator */
if (initiator_shutdown() == -1) {
TRACE_ERROR("initiator_shutdown() failed\n");
return -1;
}
}
printf("\n");
printf("************************************\n");
printf("* ALL TESTS COMPLETED SUCCESSFULLY *\n");
printf("************************************\n");
printf("\n");
exit(EXIT_SUCCESS);
}

111
dist/iscsi/src/iscsi-target.8 vendored Normal file
View File

@ -0,0 +1,111 @@
.\" $NetBSD: iscsi-target.8,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
.\"
.\" Copyright © 2006 Alistair Crooks. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 30, 2006
.Dt ISCSI-TARGET 8
.Os
.Sh NAME
.Nm iscsi-target
.Nd service remote iSCSI requests
.Sh SYNOPSIS
.Nm
.Op Fl D
.Op Fl b Ar block length
.Op Fl f Ar configuration file
.Op Fl p Ar port number
.Op Fl t Ar target name
.Op Fl v Ar verbose arg
.Sh DESCRIPTION
.Nm
is the server for
iSCSI
requests from iSCSI initiators.
.Nm
listens for discovery and login requests on the port specified in the
.Xr targets 5
configuration file, and responds to those requests appropriately.
See
.%T "The Internet Small Computer Systems Interface" ,
RFC 3720.
.Pp
Options and operands available for
.Nm iscsi-target :
.Bl -tag -width Ds
.It Fl b Ar blocksize
Specify the underlying block size for iSCSI storage which will be served.
The possible sizes are: 512, 1024, 2048, and 4096 bytes, with the default
being 512 bytes.
.It Fl D
When this option is specified,
.Nm
will not detach itself from the controlling tty, and will
not become a daemon.
This can be useful for debugging purposes.
.It Fl f Ar configfile
Use the named file as the configuration file.
The default file can be found in
.Ar /etc/iscsi/targets .
See
.Xr targets 5
for more information.
.It Fl p Ar port number
Use the port number provided as the argument as the port
on which to listen for iSCSI service requests from
initiators.
.It Fl t Ar filename
The target name (as it appears to the iSCSI initiator) can be specified
using this flag.
.It Fl v Ar argument
The amount of information shown can be varied by using this command.
Possible values of
.Ar argument
are
.Ar net
to show network-related information,
.Ar iscsi
to show iSCSI protocol-related information,
.Ar scsi
to show SCSI protocol information, and
.Ar all
to show information from all of the above arguments.
.El
.Sh FILES
.Bl -tag -width /var/run/iscsi-target.pid -compact
.It Pa /etc/iscsi/targets
the list of exported storage
.It Pa /var/run/iscsi-target.pid
the PID of the currently running
.Nm
.El
.Sh SEE ALSO
.Xr targets 5
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 4.0 .

475
dist/iscsi/src/iscsi-target.c vendored Normal file
View File

@ -0,0 +1,475 @@
/* $NetBSD: iscsi-target.c,v 1.1.1.1 2006/02/08 18:56:16 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Alistair Crooks
* for the NetBSD project.
* 4. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define EXTERN
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <unistd.h>
#include "iscsi.h"
#include "util.h"
#include "target.h"
#include "device.h"
#include "conffile.h"
#include "storage.h"
/* let's use symbolic names for the fields in the config file */
enum {
EXTENT_NAME_COL = 0,
EXTENT_DEVICE_COL = 1,
EXTENT_SACRED_COL = 2,
EXTENT_LENGTH_COL = 3,
DEVICE_NAME_COL = 0,
DEVICE_RAIDLEVEL_COL = 1,
DEVICE_LENGTH_COL = 2,
TARGET_NAME_COL = 0,
TARGET_DEVICE_COL = 1,
TARGET_NETMASK_COL = 2
};
static int g_main_pid;
static globals_t g;
/* find an extent by name */
static disc_extent_t *
find_extent(extv_t *evp, char *s)
{
int i;
for (i = 0 ; i < evp->c ; i++) {
if (strcmp(evp->v[i].extent, s) == 0) {
return &evp->v[i];
}
}
return NULL;
}
/* allocate space for a new extent */
static int
do_extent(conffile_t *cf, extv_t *evp, ent_t *ep)
{
char *cp;
if (find_extent(evp, ep->sv.v[EXTENT_NAME_COL]) != NULL) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: attempt to re-define extent `%s'\n", ep->sv.v[EXTENT_NAME_COL]);
return 0;
}
ALLOC(disc_extent_t, evp->v, evp->size, evp->c, 14, 14, "do_extent", exit(EXIT_FAILURE));
evp->v[evp->c].extent = strdup(ep->sv.v[EXTENT_NAME_COL]);
evp->v[evp->c].dev = strdup(ep->sv.v[EXTENT_DEVICE_COL]);
evp->v[evp->c].sacred = strtoll(ep->sv.v[EXTENT_SACRED_COL], NULL, 10);
evp->v[evp->c].len = strtoll(ep->sv.v[EXTENT_LENGTH_COL], &cp, 10);
if (cp != NULL) {
switch(tolower((unsigned)*cp)) {
case 't':
evp->v[evp->c].len *= (uint64_t)(1024ULL * 1024ULL * 1024ULL * 1024ULL);
break;
case 'g':
evp->v[evp->c].len *= (uint64_t)(1024ULL * 1024ULL * 1024ULL);
break;
case 'm':
evp->v[evp->c].len *= (uint64_t)(1024ULL * 1024ULL);
break;
case 'k':
evp->v[evp->c].len *= (uint64_t)1024ULL;
break;
}
}
evp->c += 1;
return 1;
}
/* find a device by name */
static disc_device_t *
find_device(devv_t *devvp, char *s)
{
int i;
for (i = 0 ; i < devvp->c ; i++) {
if (strcmp(devvp->v[i].dev, s) == 0) {
return &devvp->v[i];
}
}
return NULL;
}
/* return the size of the sub-device/extent */
static uint64_t
getsize(conffile_t *cf, devv_t *devvp, extv_t *evp, char *s)
{
disc_extent_t *xp;
disc_device_t *dp;
if ((xp = find_extent(evp, s)) != NULL) {
return xp->len;
}
if ((dp = find_device(devvp, s)) != NULL) {
switch (dp->xv[0].type) {
case DE_EXTENT:
return dp->xv[0].u.xp->len;
case DE_DEVICE:
return dp->xv[0].u.dp->len;
}
}
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Warning: sub-device/extent `%s' not found\n", s);
return 0;
}
/* allocate space for a device */
static int
do_device(conffile_t *cf, devv_t *devvp, extv_t *evp, ent_t *ep)
{
if (find_device(devvp, ep->sv.v[DEVICE_NAME_COL]) != NULL) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: attempt to re-define device `%s'\n", ep->sv.v[DEVICE_NAME_COL]);
return 0;
}
ALLOC(disc_device_t, devvp->v, devvp->size, devvp->c, 14, 14, "do_device", exit(EXIT_FAILURE));
devvp->v[devvp->c].dev = strdup(ep->sv.v[DEVICE_NAME_COL]);
devvp->v[devvp->c].raid = (strncasecmp(ep->sv.v[DEVICE_RAIDLEVEL_COL], "raid", 4) == 0) ? atoi(&ep->sv.v[DEVICE_RAIDLEVEL_COL][4]) : 0;
devvp->v[devvp->c].size = ep->sv.c - 2;
devvp->v[devvp->c].len = getsize(cf, devvp, evp, ep->sv.v[DEVICE_LENGTH_COL]);
NEWARRAY(disc_de_t, devvp->v[devvp->c].xv, ep->sv.c - 2, "do_device", exit(EXIT_FAILURE));
for (devvp->v[devvp->c].c = 0 ; devvp->v[devvp->c].c < devvp->v[devvp->c].size ; devvp->v[devvp->c].c++) {
if ((devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp = find_extent(evp, ep->sv.v[devvp->v[devvp->c].c + 2])) != NULL) {
if (devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp->used) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: extent `%s' has already been used\n", ep->sv.v[devvp->v[devvp->c].c + 2]);
return 0;
}
if (devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp->len != devvp->v[devvp->c].len) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: extent `%s' has size %lld, not %lld\n", ep->sv.v[devvp->v[devvp->c].c + 2], devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp->len, devvp->v[devvp->c].len);
return 0;
}
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].type = DE_EXTENT;
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].size = devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp->len;
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.xp->used = 1;
} else if ((devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.dp = find_device(devvp, ep->sv.v[devvp->v[devvp->c].c + 2])) != NULL) {
if (devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.dp->used) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: device `%s' has already been used\n", ep->sv.v[devvp->v[devvp->c].c + 2]);
return 0;
}
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].type = DE_DEVICE;
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.dp->used = 1;
devvp->v[devvp->c].xv[devvp->v[devvp->c].c].size = devvp->v[devvp->c].xv[devvp->v[devvp->c].c].u.dp->len;
} else {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: no extent or device found for `%s'\n", ep->sv.v[devvp->v[devvp->c].c + 2]);
return 0;
}
}
if (devvp->v[devvp->c].raid == 1) {
/* check we have more than 1 device/extent */
if (devvp->v[devvp->c].c < 2) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: device `%s' is specified as RAID1, but has only %d sub-devices/extents\n", devvp->v[devvp->c].dev, devvp->v[devvp->c].c);
return 0;
}
}
devvp->c += 1;
return 1;
}
/* find a target by name */
static disc_target_t *
find_target(targv_t *tvp, char *s)
{
int i;
for (i = 0 ; i < tvp->c ; i++) {
if (strcmp(tvp->v[i].target, s) == 0) {
return &tvp->v[i];
}
}
return NULL;
}
/* allocate space for a new target */
static int
do_target(conffile_t *cf, targv_t *tvp, devv_t *devvp, extv_t *evp, ent_t *ep)
{
disc_extent_t *xp;
disc_device_t *dp;
if (find_target(tvp, ep->sv.v[TARGET_NAME_COL]) != NULL) {
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: attempt to re-define target `%s'\n", ep->sv.v[TARGET_NAME_COL]);
return 0;
}
ALLOC(disc_target_t, tvp->v, tvp->size, tvp->c, 14, 14, "do_target", exit(EXIT_FAILURE));
if ((dp = find_device(devvp, ep->sv.v[TARGET_DEVICE_COL])) != NULL) {
tvp->v[tvp->c].de.type = DE_DEVICE;
tvp->v[tvp->c].de.u.dp = dp;
tvp->v[tvp->c].target = strdup(ep->sv.v[TARGET_NAME_COL]);
tvp->v[tvp->c].mask = strdup(ep->sv.v[TARGET_NETMASK_COL]);
tvp->c += 1;
return 1;
}
if ((xp = find_extent(evp, ep->sv.v[TARGET_DEVICE_COL])) != NULL) {
tvp->v[tvp->c].de.type = DE_EXTENT;
tvp->v[tvp->c].de.u.xp = xp;
tvp->v[tvp->c].target = strdup(ep->sv.v[TARGET_NAME_COL]);
tvp->v[tvp->c].mask = strdup(ep->sv.v[TARGET_NETMASK_COL]);
tvp->c += 1;
return 1;
}
(void) fprintf(stderr, "%s:%d: ", conffile_get_name(cf), conffile_get_lineno(cf));
(void) fprintf(stderr, "Error: no device or extent found for `%s'\n", ep->sv.v[TARGET_DEVICE_COL]);
return 0;
}
/* print an extent */
static void
pextent(disc_extent_t *ep, int indent)
{
int i;
for (i = 0 ; i < indent ; i++) {
(void) fputc('\t', stdout);
}
printf("%s:%s:%lld:%lld\n", ep->extent, ep->dev, ep->sacred, ep->len);
}
static void pdevice(disc_device_t *, int);
/* print information about an extent or a device */
static void
pu(disc_de_t *dep, int indent)
{
switch(dep->type) {
case DE_EXTENT:
pextent(dep->u.xp, indent);
break;
case DE_DEVICE:
pdevice(dep->u.dp, indent);
break;
}
}
/* print information about a device */
static void
pdevice(disc_device_t *dp, int indent)
{
int i;
int j;
for (i = 0 ; i < indent ; i++) {
(void) fputc('\t', stdout);
}
printf("%s:RAID%d\n", dp->dev, dp->raid);
for (j = 0 ; j < dp->c ; j++) {
pu(&dp->xv[j], indent + 1);
}
}
/* print informnation about a target */
static void
ptarget(disc_target_t *tp, int indent)
{
int i;
for (i = 0 ; i < indent ; i++) {
(void) fputc('\t', stdout);
}
printf("%s:%s\n", tp->target, tp->mask);
pu(&tp->de, indent + 1);
}
/* print all information */
static void
ptargets(targv_t *tvp)
{
int i;
for (i = 0 ; i < tvp->c ; i++) {
ptarget(&tvp->v[i], 0);
}
}
static int
read_conf_file(const char *cf, targv_t *tvp, devv_t *dvp, extv_t *evp)
{
conffile_t conf;
ent_t e;
(void) memset(&conf, 0x0, sizeof(conf));
if (!conffile_open(&conf, cf, "r", " \t", "#")) {
(void) fprintf(stderr, "Error: can't open `%s'\n", cf);
return 0;
}
PRINT("Reading configuration from `%s'\n", cf);
(void) memset(&e, 0x0, sizeof(e));
while (conffile_getent(&conf, &e)) {
if (strncmp(e.sv.v[0], "extent", 6) == 0) {
do_extent(&conf, evp, &e);
} else if (strncmp(e.sv.v[0], "device", 6) == 0) {
do_device(&conf, dvp, evp, &e);
} else if (strncmp(e.sv.v[0], "target", 6) == 0) {
do_target(&conf, tvp, dvp, evp, &e);
}
e.sv.c = 0;
}
ptargets(tvp);
(void) conffile_close(&conf);
return 1;
}
/* write the pid to the pid file */
static void
write_pid_file(void)
{
FILE *fp;
if ((fp = fopen(_PATH_ISCSI_PID_FILE, "w")) == NULL) {
(void) fprintf(stderr, "Couldn't create pid file \"%s\": %s", _PATH_ISCSI_PID_FILE, strerror(errno));
} else {
fprintf(fp, "%ld\n", (long) getpid());
fclose(fp);
}
}
int
main(int argc, char **argv)
{
const char *cf;
targv_t tv;
devv_t dv;
extv_t ev;
char TargetName[1024];
int detach_me_harder;
int i;
(void) memset(&g, 0x0, sizeof(g));
(void) memset(&tv, 0x0, sizeof(tv));
(void) memset(&dv, 0x0, sizeof(dv));
(void) memset(&ev, 0x0, sizeof(ev));
/* set defaults */
(void) strlcpy(TargetName, DEFAULT_TARGET_NAME, sizeof(TargetName));
detach_me_harder = 1;
g.port = ISCSI_PORT;
cf = _PATH_ISCSI_TARGETS;
while ((i = getopt(argc, argv, "Db:f:p:t:v:")) != -1) {
switch (i) {
case 'D':
detach_me_harder = 0;
break;
case 'b':
device_set_var("blocklen", optarg);
break;
case 'f':
cf = optarg;
break;
case 'p':
g.port = (uint16_t) atoi(optarg);
break;
case 't':
(void) strlcpy(TargetName, optarg, sizeof(TargetName));
break;
case 'v':
if (strcmp(optarg, "net") == 0) {
set_debug("net");
} else if (strcmp(optarg, "iscsi") == 0) {
set_debug("iscsi");
} else if (strcmp(optarg, "scsi") == 0) {
set_debug("scsi");
} else if (strcmp(optarg, "all") == 0) {
set_debug("all");
}
break;
}
}
if (!read_conf_file(cf, &tv, &dv, &ev)) {
(void) fprintf(stderr, "Error: can't open `%s'\n", cf);
return EXIT_FAILURE;
}
(void) signal(SIGPIPE, SIG_IGN);
g_main_pid = ISCSI_GETPID;
if (tv.c == 0) {
(void) fprintf(stderr, "No targets to initialise\n");
return EXIT_FAILURE;
}
/* Initialize target */
for (i = 0 ; i < tv.c ; i++) {
if (target_init(&g, &tv, TargetName, i) != 0) {
TRACE_ERROR("target_init() failed\n");
exit(EXIT_FAILURE);
}
}
#ifdef HAVE_DAEMON
/* if we are supposed to be a daemon, detach from controlling tty */
if (detach_me_harder && daemon(0, 0) < 0) {
TRACE_ERROR("daemon() failed\n");
exit(EXIT_FAILURE);
}
#endif
/* write pid to a file */
write_pid_file();
/* Wait for connections */
if (target_listen(&g) != 0) {
TRACE_ERROR("target_listen() failed\n");
}
return EXIT_SUCCESS;
}

1342
dist/iscsi/src/iscsi.c vendored Normal file

File diff suppressed because it is too large Load Diff

76
dist/iscsi/src/ktarget.c vendored Normal file
View File

@ -0,0 +1,76 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
#include "iscsi.h"
#include "iscsi.c"
#include "util.h"
#include "util.c"
#include "target.h"
#include "target.c"
#include "device.h"
#include "disk.c"
#include "parameters.h"
#include "parameters.c"
/* Parameters */
static int port = ISCSI_PORT; MODULE_PARM(port, "i");
static int accept_connections(void *arg) {
if (target_listen(port)!=0) {
TRACE_ERROR("target_listen() failed\n");
}
return 0;
}
int init_module(void) {
printk("\n");
printk("Usage: port=<int>\n");
printk("\n");
if (target_init(DEFAULT_TARGET_NAME)!=0) {
TRACE_ERROR("target_init() failed\n");
return -1;
}
kernel_thread(accept_connections, NULL, 0);
return 0;
}
void cleanup_module(void) {
if (target_shutdown()!=0) {
TRACE_ERROR("target_shutdown() failed\n");
}
}

59
dist/iscsi/src/ktest.c vendored Normal file
View File

@ -0,0 +1,59 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fd;
if (argc!=2) {
printf("usage: %s <device>\n", argv[0]);
return -1;
}
if ((fd=open(argv[1], O_RDONLY))==-1) {
printf("error opening %s\n", argv[1]);
return -1;
}
printf("******************************************************\n");
printf("* Test is running. View output in /var/log/messages. *\n");
printf("******************************************************\n");
ioctl(fd, 0, NULL);
close(fd);
return 0;
}

10
dist/iscsi/src/lint.mk vendored Normal file
View File

@ -0,0 +1,10 @@
PROG= ../bin/iscsi-target
SRCS= disk.c iscsi-target.c target.c iscsi.c util.c parameters.c
CPPFLAGS+= -DCONFIG_ISCSI_DEBUG -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
CPPFLAGS+= -I${.CURDIR}/../include
CPPFLAGS+= -pthread
LDFLAGS+= -pthread
NOMAN= # defined
WARNS=4
.include <bsd.prog.mk>

241
dist/iscsi/src/md5.c vendored Normal file
View File

@ -0,0 +1,241 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*
* Changed so as no longer to depend on Colin Plumb's `usual.h' header
* definitions; now uses stuff from dpkg's config.h.
* - Ian Jackson <ijackson@nyx.cs.du.edu>.
* Still in the public domain.
*/
#ifndef __KERNEL__
#include <string.h>
#include <netinet/in.h>
#endif
#include "md5.h"
#ifdef WORDS_BIGENDIAN
void
byteSwap(UWORD32 *buf, uint32_t words)
{
md5byte *p = (md5byte *)buf;
do {
*buf++ = (UWORD32)((uint32_t)p[3] << 8 | p[2]) << 16 |
((uint32_t)p[1] << 8 | p[0]);
p += 4;
} while (--words);
}
#else
#define byteSwap(buf,words)
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bytes[0] = 0;
ctx->bytes[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
MD5Update(struct MD5Context *ctx, md5byte const *buf, uint32_t len)
{
UWORD32 t;
/* Update byte count */
t = ctx->bytes[0];
if ((ctx->bytes[0] = t + len) < t)
ctx->bytes[1]++; /* Carry from low to high */
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
if (t > len) {
memcpy((md5byte *)ctx->in + 64 - t, buf, len);
return;
}
/* First chunk is an odd size */
memcpy((md5byte *)ctx->in + 64 - t, buf, t);
byteSwap(ctx->in, 16);
MD5Transform(ctx->buf, ctx->in);
buf += t;
len -= t;
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteSwap(ctx->in, 16);
MD5Transform(ctx->buf, ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void
MD5Final(md5byte digest[16], struct MD5Context *ctx)
{
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
md5byte *p = (md5byte *)ctx->in + count;
/* Set the first char of padding to 0x80. There is always room. */
*p++ = 0x80;
/* Bytes of padding needed to make 56 bytes (-8..55) */
count = 56 - 1 - count;
if (count < 0) { /* Padding forces an extra block */
memset(p, 0, count + 8);
byteSwap(ctx->in, 16);
MD5Transform(ctx->buf, ctx->in);
p = (md5byte *)ctx->in;
count = 56;
}
memset(p, 0, count);
byteSwap(ctx->in, 14);
/* Append length in bits and transform */
ctx->in[14] = ctx->bytes[0] << 3;
ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
MD5Transform(ctx->buf, ctx->in);
byteSwap(ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f,w,x,y,z,in,s) \
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
{
register UWORD32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#endif

24
dist/iscsi/src/mknodes.c vendored Normal file
View File

@ -0,0 +1,24 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(int c, char *argv[]) {
int i;
char filename[64];
for (i=0; i<256; i++) {
sprintf(filename, "/dev/so%c%c", 'a'+i/26, 'a'+i%26);
sprintf(filename, "/dev/so%i", i);
printf("%i: %s (%i/%i)\n", i, filename, 232, i);
if (mknod(filename, S_IFBLK, (232<<8)|(i&255))==-1) {
printf("mknod() failed: errno %i\n", errno);
return -1;
}
getchar();
}
return 0;
}

288
dist/iscsi/src/mount_iscsi.c vendored Normal file
View File

@ -0,0 +1,288 @@
/* $NetBSD: mount_iscsi.c,v 1.1.1.1 2006/02/08 18:56:18 agc Exp $ */
/*
* Copyright © 2005 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright © 2005 \
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: mount_iscsi.c,v 1.1.1.1 2006/02/08 18:56:18 agc Exp $");
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "iscsi.h"
#include "initiator.h"
#include "tests.h"
static int verbose;
enum {
ISCSI_DOMAIN_NAME_SIZE = 512,
ISCSI_PRODUCT_NAME_SIZE = 256,
ISCSI_TARGET_NAME_SIZE = 256,
ISCSI_LUN_NAME_SIZE = 64,
MAX_DOMAIN_PARTS = 100
};
/* iSCSI addresses are specified using an IQN, or iSCSI Qualified Name */
/* this structure is used to unpack the components of an IQN */
typedef struct iqn_t {
char revdomain[ISCSI_DOMAIN_NAME_SIZE];
char domain[ISCSI_DOMAIN_NAME_SIZE];
char product[ISCSI_PRODUCT_NAME_SIZE];
char target[ISCSI_TARGET_NAME_SIZE];
char lun[ISCSI_LUN_NAME_SIZE];
struct sockaddr_in sock;
int socklen;
} iqn_t;
/* regular expression used to parse IQNs */
#define IQN_PARSE "iqn\\.[^.]*\\.(.*)\\.([^.]*)\\.([^.]*)\\.([^.]*)"
/* copy a name to an output array */
static void
copyname(char *array, size_t size, char *s, int from, int to, const char *field)
{
if (to - from > size - 1) {
warnx("truncating %s `%.*s'", field, (int)(to - from), &s[from]);
}
(void) strlcpy(array, &s[from], MIN((int)(to - from + 1), size));
}
/* reverse the components of the domain name */
static void
reversedomain(char *in, char *out, size_t size)
{
char *cp;
char *dots[MAX_DOMAIN_PARTS];
int dotc;
int i;
for (cp = in, dotc = 0 ; *cp != 0x0 && dotc < MAX_DOMAIN_PARTS ; cp++) {
if (*cp == '.') {
dots[dotc++] = cp;
}
}
(void) memset(out, 0x0, size);
for (cp = out, i = dotc - 1 ; i >= 0 ; --i) {
cp += snprintf(cp, size - (int)(cp - out), "%s%.*s",
(i == dotc - 1) ? "" : ".",
(i == dotc - 1) ? strlen(dots[i]) - 1 : (int)(dots[i + 1] - dots[i] - 1),
dots[i] + 1);
}
(void) snprintf(cp, size - (int)(cp - out), "%s%.*s", ".", (int)(dots[0] - in), in);
}
/* iqn.2003-02.com.alistaircrooks.product.target.lun */
static int
iqnparse(char *s, iqn_t *iqn)
{
static int done;
regmatch_t matchv[10];
regex_t r;
(void) memset(iqn, 0x0, sizeof(*iqn));
if (!done) {
(void) memset(&r, 0x0, sizeof(r));
if (regcomp(&r, IQN_PARSE, REG_EXTENDED) != 0) {
warn("failed to compile iqn parse string");
}
done = 1;
}
if (regexec(&r, s, 10, matchv, 0) != 0) {
warnx("iqnparse: invalid IQN - `%s'", s);
return 0;
}
/* get the domain name from the iqn and reverse it */
copyname(iqn->revdomain, sizeof(iqn->revdomain), s, (int)(matchv[1].rm_so), (int)(matchv[1].rm_eo), "revdomain");
reversedomain(iqn->revdomain, iqn->domain, sizeof(iqn->domain));
/* get the product name from the iqn */
copyname(iqn->product, sizeof(iqn->product), s, (int)(matchv[2].rm_so), (int)(matchv[2].rm_eo), "product");
/* get the target name from the iqn */
copyname(iqn->target, sizeof(iqn->target), s, (int)(matchv[3].rm_so), (int)(matchv[3].rm_eo), "target");
/* get the lun from the iqn */
copyname(iqn->lun, sizeof(iqn->lun), s, (int)(matchv[4].rm_so), (int)(matchv[4].rm_eo), "lun");
return 1;
}
/* make a connection to an IQN */
static int
make_connection(char *hostname, iqn_t *iqn)
{
struct addrinfo hints;
struct addrinfo *res;
struct addrinfo *res0 = NULL;
volatile int s;
in_port_t portnum;
char hbuf[NI_MAXHOST];
char service[32];
char *host;
int error;
(void) memset(iqn, 0x0, sizeof(*iqn));
(void) iqnparse(hostname, iqn);
printf("revdomain: `%s'\n", iqn->revdomain);
printf("domain: `%s'\n", iqn->domain);
printf("product: `%s'\n", iqn->product);
printf("target: `%s'\n", iqn->target);
printf("lun: `%s'\n", iqn->lun);
(void) memset(&hints, 0x0, sizeof(hints));
(void) strlcpy(service, "iscsi", sizeof(service));
hints.ai_flags = 0;
hints.ai_family = AF_INET; /* expand this to IPv6 at the right time - XXX */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((error = getaddrinfo(host = iqn->domain, NULL, &hints, &res0)) != 0) {
warnx("%s: %s", host, gai_strerror(error));
return 0;
}
if (res0->ai_canonname) {
host = res0->ai_canonname;
}
s = -1;
for (res = res0; res; res = res->ai_next) {
#if 0
/* XXX fixme */
/*
* see comment in hookup()
*/
ai_unmapped(res);
#endif
if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), service, sizeof(service), NI_NUMERICHOST) != 0) {
strlcpy(hbuf, "invalid", sizeof(hbuf));
}
((struct sockaddr_in *)res->ai_addr)->sin_port = htons(portnum);
(void) memcpy(&iqn->sock, &res->ai_addr, sizeof(res->ai_addr));
iqn->socklen = res->ai_addrlen;
return 1;
#if 0
if ((s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol)) < 0) {
warn("Can't create socket");
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
warn("Connect to address `%s'", hbuf);
close(s);
s = -1;
continue;
}
#endif
}
return 0;
}
int
main(int argc, char **argv)
{
struct sigaction act;
iqn_t iqn;
int begin_tid = 0;
int end_tid = CONFIG_INITIATOR_NUM_TARGETS;
int lun = 0;
int i;
int j;
while ((i = getopt(argc, argv, "v")) != -1) {
switch(i) {
case 'v':
verbose += 1;
break;
default:
errx(EXIT_FAILURE, "Unknown option `%c'", i);
break;
}
}
if (argc - optind != 2) {
errx(EXIT_FAILURE, "Usage: %s [-v] iqn mountpoint\n", *argv);
}
(void) memset(&iqn, 0x0, sizeof(iqn));
if (!make_connection(argv[optind], &iqn)) {
exit(EXIT_FAILURE);
}
for (j = 0; j < 1; j++) {
PRINT("<ITER %i>\n", j);
/* Ignore sigpipe */
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
/* Initialize Initiator */
if (initiator_init(iqn.domain) == -1) {
TRACE_ERROR("initiator_init() failed\n");
return -1;
}
/* Run tests for each target */
for (i = begin_tid; i < end_tid; i++) {
if (test_all(i, lun) != 0) {
TRACE_ERROR("test_all() failed\n");
return -1;
}
}
/* Shutdown Initiator */
if (initiator_shutdown() == -1) {
TRACE_ERROR("initiator_shutdown() failed\n");
return -1;
}
}
exit(EXIT_SUCCESS);
}

149
dist/iscsi/src/osd-target.c vendored Normal file
View File

@ -0,0 +1,149 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define EXTERN
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <unistd.h>
#include "iscsi.h"
#include "util.h"
#include "target.h"
#include "device.h"
/*
* Globals
*/
static int g_main_pid;
static globals_t g;
/*
* Control-C handler
*/
/* ARGSUSED0 */
static void
handler(int s)
{
if (ISCSI_GETPID != g_main_pid)
return;
if (target_shutdown(&g) != 0) {
TRACE_ERROR("target_shutdown() failed\n");
return;
}
return;
}
int
main(int argc, char **argv)
{
char TargetName[1024];
int i;
(void) memset(&g, 0x0, sizeof(g));
/* set defaults */
(void) strlcpy(TargetName, DEFAULT_TARGET_NAME, sizeof(TargetName));
g.port = ISCSI_PORT;
while ((i = getopt(argc, argv, "c:l:d:" "p:t:v:")) != -1) {
switch (i) {
case 'c':
device_set_var("capacity", optarg);
break;
case 'd':
device_set_var("directory", optarg);
break;
case 'l':
device_set_var("luns", optarg);
break;
case 'p':
g.port = (uint16_t) atoi(optarg);
break;
case 't':
(void) strlcpy(TargetName, optarg, sizeof(TargetName));
break;
case 'v':
if (strcmp(optarg, "net") == 0) {
set_debug("net");
} else if (strcmp(optarg, "iscsi") == 0) {
set_debug("iscsi");
} else if (strcmp(optarg, "scsi") == 0) {
set_debug("scsi");
} else if (strcmp(optarg, "osd") == 0) {
set_debug("osd");
} else if (strcmp(optarg, "all") == 0) {
set_debug("all");
}
break;
}
}
(void) signal(SIGPIPE, SIG_IGN);
(void) signal(SIGINT, handler);
g_main_pid = ISCSI_GETPID;
/* Initialize target */
if (optind == argc) {
if (target_init(&g, TargetName, NULL) != 0) {
TRACE_ERROR("target_init() failed\n");
exit(EXIT_FAILURE);
}
} else {
for (i = optind ; i < argc ; i++) {
if (target_init(&g, TargetName, argv[i]) != 0) {
TRACE_ERROR("target_init() failed\n");
exit(EXIT_FAILURE);
}
}
}
/* Wait for connections */
if (target_listen(&g) != 0) {
TRACE_ERROR("target_listen() failed\n");
}
return EXIT_SUCCESS;
}

662
dist/iscsi/src/osd.c vendored Normal file
View File

@ -0,0 +1,662 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <unistd.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <unistd.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#include "scsi_cmd_codes.h"
#include "iscsi.h"
#include "util.h"
#include "device.h"
#include "osd.h"
/*
* Globals
*/
static int osd_luns = CONFIG_OSD_LUNS_DFLT;
static uint64_t osd_capacity = CONFIG_OSD_CAPACITY_DFLT * 1048576;
static char base_dir[64] = CONFIG_OSD_BASEDIR_DFLT;
#ifndef __KERNEL__
void
device_set_var(const char *var, char *arg)
{
if (strcmp(var, "capacity") == 0) {
osd_capacity = strtoll(arg, (char **) NULL, 10) * 1048576;
} else if (strcmp(var, "luns") == 0) {
osd_luns = atoi(arg);
} else if (strcmp(var, "directory") == 0) {
(void) strlcpy(base_dir, arg, sizeof(base_dir));
} else {
(void) fprintf(stderr, "Unrecognised variable: `%s'\n", var);
}
}
#endif
int
device_init(globals_t *gp, char *dev)
{
struct stat st;
char FileName[1024];
int i;
if (stat(base_dir, &st) < 0) {
/* Create directory for OSD */
if (mkdir(base_dir, 0755) != 0) {
if (errno != EEXIST) {
TRACE_ERROR("error creating directory \"%s\" for OSD: errno %i\n", base_dir, errno);
return -1;
}
}
/* Create directory for LU */
for (i = 0; i < osd_luns; i++) {
sprintf(FileName, "%s/lun_%i", base_dir, i);
if (mkdir(FileName, 0755) != 0) {
if (errno != EEXIST) {
TRACE_ERROR("error creating \"%s\" for LU %i: errno %i\n", FileName, i, errno);
return -1;
}
}
}
}
/* Display LU info */
return 0;
}
int
osd_read_callback(void *arg)
{
struct iovec *sg = (struct iovec *) arg;
int i = 0;
while (sg[i].iov_base != NULL) {
iscsi_free_atomic(sg[i].iov_base);
i++;
}
return 0;
}
int
device_command(target_session_t * sess, target_cmd_t * cmd)
{
iscsi_scsi_cmd_args_t *args = cmd->scsi_cmd;
uint8_t *data;
char FileName[1024];
uint8_t *write_data = NULL;
uint8_t *read_data = NULL;
uint8_t *set_list = NULL;
uint8_t *get_list = NULL;
struct iovec sg[3];
int sg_len = 0;
int rc;
osd_args_t osd_args;
uint32_t GroupID = 0;
uint64_t UserID = 0;
char string[1024];
uint8_t *get_data = NULL;
uint32_t page = 0;
uint32_t index = 0;
int attr_len = 0;
TRACE(TRACE_SCSI_CMD, "SCSI op 0x%x (lun %llu)\n", args->cdb[0], args->lun);
if (args->lun >= osd_luns) {
TRACE(TRACE_SCSI_DEBUG, "invalid lun: %llu\n", args->lun);
args->status = 0x01;
return 0;
}
args->status = 1;
switch (args->cdb[0]) {
case TEST_UNIT_READY:
TRACE(TRACE_SCSI_CMD, "TEST_UNIT_READY(lun %llu)\n", args->lun);
args->status = 0;
args->length = 0;
break;
case INQUIRY:
TRACE(TRACE_SCSI_CMD, "INQUIRY(lun %llu)\n", args->lun);
data = args->send_data;
memset(data, 0, args->cdb[4]); /* Clear allocated buffer */
data[0] = 0x0e; /* Peripheral Device Type */
/* data[1] |= 0x80; // Removable Bit */
data[2] |= 0x02;/* ANSI-approved version */
/* data[3] |= 0x80; // AENC */
/* data[3] |= 0x40; // TrmIOP */
/* data[3] |= 0x20; // NormACA */
data[4] = args->cdb[4] - 4; /* Additional length */
/*
* data[7] |= 0x80; // Relative
* addressing
*/
data[7] |= 0x40;/* WBus32 */
data[7] |= 0x20;/* WBus16 */
/* data[7] |= 0x10; // Sync */
/* data[7] |= 0x08; // Linked Commands */
/* data[7] |= 0x04; // TransDis */
/*
* data[7] |= 0x02; // Tagged Command
* Queueing
*/
/* data[7] |= 0x01; // SftRe */
(void) memset(data + 8, 0x0, 32);
strlcpy(data + 8, OSD_VENDOR, 8); /* Vendor */
strlcpy(data + 16, OSD_PRODUCT, 16); /* Product ID */
(void) snprintf(data + 32, 8, "%d", OSD_VERSION); /* Product Revision */
args->input = 1;
args->length = args->cdb[4] + 1;
args->status = 0;
break;
case 0x7F:
OSD_DECAP_CDB(args->cdb, args->ext_cdb, &osd_args);
/* OSD_PRINT_CDB(args->cdb, args->ext_cdb); */
GroupID = osd_args.GroupID;
UserID = osd_args.UserID;
/*
* Transfer all data
*/
if (osd_args.set_attributes_list_length) {
if ((set_list = iscsi_malloc_atomic(osd_args.set_attributes_list_length)) == NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
goto done;
}
sg[sg_len].iov_base = set_list;
sg[sg_len].iov_len = osd_args.set_attributes_list_length;
sg_len++;
}
if (osd_args.get_attributes_list_length) {
if ((get_list = iscsi_malloc_atomic(osd_args.get_attributes_list_length)) == NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
goto done;
}
sg[sg_len].iov_base = get_list;
sg[sg_len].iov_len = osd_args.get_attributes_list_length;
sg_len++;
}
if (osd_args.service_action == OSD_WRITE) {
if ((write_data = iscsi_malloc_atomic(osd_args.length)) == NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
goto done;
}
sg[sg_len].iov_base = write_data;
sg[sg_len].iov_len = osd_args.length;
sg_len++;
}
if (sg_len) {
if (target_transfer_data(sess, args, sg, sg_len) != 0) {
TRACE_ERROR("target_transfer_data() failed\n");
goto done;
}
}
/*
* Set any attributes
*/
if (osd_args.set_attributes_list_length) {
uint32_t page, attr;
uint16_t len;
int i;
TRACE(TRACE_OSD, "OSD_SET_ATTR(lun %llu, GroupID 0x%x, UserID 0x%llx)\n", args->lun, osd_args.GroupID, osd_args.UserID);
for (i = 0; i < osd_args.set_attributes_list_length;) {
page = ISCSI_NTOHL(*((uint32_t *) (&(set_list[i]))));
i += 4;
attr = ISCSI_NTOHL(*((uint32_t *) (&(set_list[i]))));
i += 4;
len = ISCSI_NTOHS(*((uint16_t *) (&(set_list[i]))));
i += 2;
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, attr);
if ((rc = open(FileName, O_WRONLY | O_CREAT, 0644)) == -1) {
TRACE_ERROR("error opening \"%s\": errno %i\n", FileName, errno);
goto done;
}
if (write(rc, set_list + i, len) != len) {
TRACE_ERROR("write() failed\n");
}
close(rc);
i += len;
TRACE(TRACE_OSD, "SET(0x%x,%u,%u>\n", page, attr, len);
}
}
args->send_sg_len = 0;
sg_len = 0;
switch (osd_args.service_action) {
case OSD_CREATE_GROUP:
do {
GroupID = rand() % 1048576 * 1024 + 1;
sprintf(FileName, "%s/lun_%llu/0x%x", base_dir, args->lun, GroupID);
rc = mkdir(FileName, 0755);
} while (rc == -1 && errno == EEXIST);
TRACE(TRACE_OSD, "OSD_CREATE_GROUP(lun %llu) --> 0x%x\n", args->lun, GroupID);
args->status = 0;
break;
case OSD_REMOVE_GROUP:
TRACE(TRACE_OSD, "OSD_REMOVE_GROUP(lun %llu, 0x%x)\n", args->lun, osd_args.GroupID);
sprintf(FileName, "%s/lun_%llu/0x%x", base_dir, args->lun, osd_args.GroupID);
if ((rc = rmdir(FileName)) == -1) {
TRACE_ERROR("rmdir(\"%s\") failed: errno %i\n", FileName, errno);
goto done;
}
args->status = 0;
break;
case OSD_CREATE:
UserID = rand() % 1048576 * 1024 + 1;
create_user_again:
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
base_dir, args->lun, osd_args.GroupID, UserID);
rc = open(FileName, O_CREAT | O_EXCL | O_RDWR, 0644);
if ((rc == -1) && (errno == EEXIST)) {
UserID = rand() % 1048576 * 1024 + 1;
goto create_user_again;
}
close(rc);
TRACE(TRACE_OSD, "OSD_CREATE(lun %llu, GroupID 0x%x) --> 0x%llx\n", args->lun, osd_args.GroupID, UserID);
args->status = 0;
break;
case OSD_REMOVE:
TRACE(TRACE_OSD, "OSD_REMOVE(lun %llu, 0x%llx)\n", args->lun, osd_args.UserID);
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
if ((rc = unlink(FileName)) == -1) {
TRACE_ERROR("unlink(\"%s\") failed: errno %i\n", FileName, errno);
goto done;
}
sprintf(string, "rm -f %s/lun_%llu/0x%x/0x%llx.*", base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
if (system(string) != 0) {
TRACE_ERROR("\"%s\" failed\n", string);
return -1;
}
args->status = 0;
break;
case OSD_WRITE:
TRACE(TRACE_OSD, "OSD_WRITE(lun %llu, GroupID 0x%x, UserID 0x%llx, length %llu, offset %llu)\n",
args->lun, osd_args.GroupID, osd_args.UserID, osd_args.length, osd_args.offset);
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
if ((rc = open(FileName, O_WRONLY, 0644)) == -1) {
TRACE_ERROR("error opening \"%s\": errno %i\n", FileName, errno);
goto write_done;
}
if (lseek(rc, osd_args.offset, SEEK_SET) == -1) {
TRACE_ERROR("error seeking \"%s\": errno %i\n", FileName, errno);
goto write_done;
}
if (write(rc, write_data, osd_args.length) != osd_args.length) {
TRACE_ERROR("write() failed\n");
goto write_done;
}
close(rc);
args->status = 0;
write_done:
break;
case OSD_READ:
TRACE(TRACE_OSD, "OSD_READ(lun %llu, GroupID 0x%x, UserID 0x%llx, length %llu, offset %llu)\n",
args->lun, osd_args.GroupID, osd_args.UserID, osd_args.length, osd_args.offset);
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
TRACE_ERROR("error opening \"%s\": errno %i\n", FileName, errno);
goto read_done;
}
if ((read_data = iscsi_malloc_atomic(osd_args.length)) == NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
goto read_done;
}
if (lseek(rc, osd_args.offset, SEEK_SET) == -1) {
TRACE_ERROR("error seeking \"%s\": errno %i\n", FileName, errno);
goto read_done;
}
if (read(rc, read_data, osd_args.length) != osd_args.length) {
TRACE_ERROR("read() failed\n");
goto read_done;
}
close(rc);
args->status = 0;
read_done:
if (args->status == 0) {
args->input = 1;
sg[0].iov_base = read_data;
sg[0].iov_len = osd_args.length;
sg[1].iov_base = NULL;
sg[1].iov_len = 0;
args->send_data = (void *) sg;
args->send_sg_len = 1;
sg_len++;
cmd->callback = osd_read_callback;
cmd->callback_arg = sg;
} else {
if (read_data)
iscsi_free_atomic(read_data);
args->length = 0; /* Need a better way of
* specifying an error.. */
}
break;
case OSD_GET_ATTR:
TRACE(TRACE_OSD, "OSD_GET_ATTR(lun %llu, GroupID 0x%x, UserID 0x%llx)\n",
args->lun, osd_args.GroupID, osd_args.UserID);
args->status = 0;
break;
case OSD_SET_ATTR:
args->status = 0;
break;
}
if (args->status)
goto done;
/*
* Send back requested attributes
*/
if (osd_args.get_attributes_list_length || osd_args.get_attributes_page) {
if ((get_data = iscsi_malloc_atomic(osd_args.get_attributes_allocation_length)) == NULL) {
TRACE_ERROR("iscsi_malloc_atomic() failed\n");
goto done;
}
}
if (osd_args.get_attributes_list_length) {
int i;
for (i = 0; i < osd_args.get_attributes_list_length;) {
page = ISCSI_NTOHL(*((uint32_t *) (&(get_list[i]))));
i += 4;
index = ISCSI_NTOHL(*((uint32_t *) (&(get_list[i]))));
i += 4;
TRACE(TRACE_OSD, "GET(0x%x,%u)\n", page, index);
switch (page) {
case 0x40000001:
switch (index) {
case 0x1:
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
attr_len += 2;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
attr_len += 4;
break;
default:
TRACE_ERROR("unknown attr index %u\n", index);
goto done;
}
break;
case 0x00000001:
switch (index) {
case 0x1:
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
attr_len += 2;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
attr_len += 4;
break;
case 0x2:
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(8);
attr_len += 2;
*((uint64_t *) & get_data[attr_len]) = ISCSI_HTONLL(UserID);
attr_len += 8;
break;
default:
TRACE_ERROR("unknown attr index %u\n", index);
goto done;
}
break;
/* Vendor-specific */
case 0x30000000:
switch (index) {
case 0x1:
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(480);
attr_len += 2;
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, index);
if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
TRACE_ERROR("error opening \"%s\": errno %i\n", FileName, errno);
}
if (read(rc, get_data + attr_len, 480) != 480) {
TRACE_ERROR("read() failed\n");
goto done;
}
close(rc);
attr_len += 480;
break;
default:
TRACE_ERROR("unknown vendor attr index %u\n", index);
goto done;
}
break;
default:
TRACE_ERROR("unknown page 0x%x\n", page);
goto done;
}
}
}
if (osd_args.get_attributes_page) {
/*
* Right now, if we get a request for an entire page,
* we return only one attribute.
*/
page = osd_args.get_attributes_page;
switch (osd_args.get_attributes_page) {
case 0x40000001:
index = 1;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
attr_len += 2;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
attr_len += 4;
break;
case 0x00000001:
index = 2;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(8);
attr_len += 2;
*((uint64_t *) & get_data[attr_len]) = ISCSI_HTONLL(UserID);
attr_len += 8;
break;
case 0x30000000:
index = 1;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
attr_len += 4;
*((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
attr_len += 4;
*((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(480);
attr_len += 2;
sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, index);
if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
TRACE_ERROR("error opening \"%s\": errno %i\n", FileName, errno);
}
if (read(rc, get_data + attr_len, 480) != 480) {
TRACE_ERROR("read() failed\n");
goto done;
}
close(rc);
attr_len += 480;
break;
default:
TRACE_ERROR("page not yet supported\n");
goto done;
}
}
if (attr_len) {
if (attr_len != osd_args.get_attributes_allocation_length) {
TRACE_ERROR("allocation lengths differ: got %u, expected %u\n",
osd_args.get_attributes_allocation_length, attr_len);
goto done;
}
if (!args->status) {
args->input = 1;
sg[sg_len].iov_base = get_data;
sg[sg_len].iov_len = osd_args.get_attributes_allocation_length;
sg_len++;
sg[sg_len].iov_base = NULL;
sg[sg_len].iov_len = 0;
args->send_data = (void *) sg;
args->send_sg_len++;
cmd->callback = osd_read_callback;
cmd->callback_arg = sg;
} else {
if (get_data)
iscsi_free_atomic(get_data);
}
}
break;
default:
TRACE_ERROR("UNKNOWN OPCODE 0x%x\n", args->cdb[0]);
args->status = 0x01;
break;
}
done:
TRACE(TRACE_SCSI_DEBUG, "SCSI op 0x%x: done (status 0x%x)\n", args->cdb[0], args->status);
if (set_list) {
iscsi_free_atomic(set_list);
}
if (get_list) {
iscsi_free_atomic(get_list);
}
if (write_data) {
iscsi_free_atomic(write_data);
}
return 0;
}
/* ARGSUSED */
int
device_shutdown(target_session_t *sess)
{
return 0;
}

410
dist/iscsi/src/osd_ops.c vendored Normal file
View File

@ -0,0 +1,410 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2002, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Transport-independent Methods
*/
#include "osd.h"
#include "util.h"
#include "osd_ops.h"
static int
extract_attribute(uint32_t page, uint32_t n, uint16_t len,
uint8_t * data, unsigned length, void *val)
{
int i = 0;
for (i = 0; i < length;) {
if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != page) {
TRACE_ERROR("page mismatch: got 0x%x, expected 0x%x\n", ISCSI_NTOHL(*(uint32_t *) (data + i)), page);
return -1;
}
i += 4;
if (ISCSI_NTOHL(*(uint32_t *) (data + i)) != n) {
TRACE_ERROR("index mismatch\n");
return -1;
}
i += 4;
if (ISCSI_NTOHS(*(uint16_t *) (data + i)) != len) {
TRACE_ERROR("len mismatch\n");
return -1;
}
i += 2;
TRACE(TRACE_DEBUG, "page 0x%x, index %u, len %u\n", page, n, len);
memcpy(val, data + i, len);
i += len;
}
TRACE(TRACE_DEBUG, "parsed %i bytes\n", i);
return i;
}
int
osd_create_group(void *dev,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
uint32_t * GroupID)
{
osd_args_t args;
#if 0
uint8_t get_list[8];
#endif
uint8_t get_data[14];
OSD_OPS_MEM mem;
mem.recv_data = get_data;
mem.recv_len = 14;
mem.recv_sg = 0;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_CREATE_GROUP;
#if 0
args.length = 8;
args.get_attributes_list_length = 8;
*((unsigned long *) get_list) = ISCSI_HTONL(0x40000001);
*((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x1);
mem.send_data = get_list;
mem.send_len = 8;
mem.send_sg = 0;
#else
args.get_attributes_page = 0x40000001;
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
#endif
args.get_attributes_allocation_length = 14;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
if (extract_attribute(0x40000001, 0x1, 4, get_data, 14, GroupID) == -1) {
TRACE_ERROR("extract_attributes() failed\n");
return -1;
}
*GroupID = ISCSI_NTOHL(*GroupID);
TRACE(TRACE_OSD, "osd_create_group() OK --> GroupID 0x%x\n", *GroupID);
return 0;
}
int
osd_create(void *dev, uint32_t GroupID,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
uint64_t * UserID)
{
osd_args_t args;
#if 0
uint8_t get_list[8];
#endif
uint8_t get_data[18];
OSD_OPS_MEM mem;
mem.recv_data = get_data;
mem.recv_len = 18;
mem.recv_sg = 0;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_CREATE;
args.GroupID = GroupID;
#if 0
args.length = 8;
args.get_attributes_list_length = 8;
*((unsigned long *) get_list) = ISCSI_HTONL(0x00000001);
*((unsigned long *) (get_list + 4)) = ISCSI_HTONL(0x2);
mem.send_data = get_list;
mem.send_len = 8;
mem.send_sg = 0;
#else
args.get_attributes_page = 0x000000001;
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
#endif
args.get_attributes_allocation_length = 18;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
if (extract_attribute(0x00000001, 0x2, 8, get_data, 18, UserID) == -1) {
TRACE_ERROR("extract_attributes() failed\n");
return -1;
}
*UserID = ISCSI_NTOHLL(*UserID);
TRACE(TRACE_OSD, "osd_create(GroupID 0x%x) OK --> UserID 0x%llx\n", GroupID, *UserID);
return 0;
}
int
osd_remove_group(void *dev, uint32_t GroupID,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
{
osd_args_t args;
OSD_OPS_MEM mem;
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
mem.recv_data = NULL;
mem.recv_len = 0;
mem.recv_sg = 0;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_REMOVE_GROUP;
args.GroupID = GroupID;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
TRACE(TRACE_OSD, "osd_remove_group(Group ID 0x%x) OK\n", GroupID);
return 0;
}
int
osd_remove(void *dev, uint32_t GroupID, uint64_t UserID,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
{
osd_args_t args;
OSD_OPS_MEM mem;
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
mem.recv_data = NULL;
mem.recv_len = 0;
mem.recv_sg = 0;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_REMOVE;
args.UserID = UserID;
args.GroupID = GroupID;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
TRACE(TRACE_OSD, "osd_remove(GroupID 0x%x, UserID 0x%llx) OK\n", GroupID, UserID);
return 0;
}
int
osd_write(void *dev,
uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, const void *send_data, int sg_len,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
{
osd_args_t args;
OSD_OPS_MEM mem;
TRACE(TRACE_OSD, "osd_write(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len);
mem.send_data = send_data;
mem.send_len = len;
mem.send_sg = sg_len;
mem.recv_data = NULL;
mem.recv_len = 0;
mem.recv_sg = 0;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_WRITE;
args.GroupID = GroupID;
args.UserID = UserID;
args.offset = offset;
args.length = len;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
return 0;
}
int
osd_read(void *dev,
uint32_t GroupID, uint64_t UserID, uint64_t offset, uint64_t len, void *recv_data, int sg_len,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
{
osd_args_t args;
OSD_OPS_MEM mem;
TRACE(TRACE_OSD, "osd_read(GroupID 0x%x, UserID 0x%llx, Offset %llu, Len %llu)\n", GroupID, UserID, offset, len);
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
mem.recv_data = recv_data;
mem.recv_len = len;
mem.recv_sg = sg_len;
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_READ;
args.GroupID = GroupID;
args.UserID = UserID;
args.offset = offset;
args.length = len;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
return 0;
}
int
osd_set_one_attr(void *dev,
uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t len, void *value,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem))
{
osd_args_t args;
OSD_OPS_MEM mem;
uint8_t list[10];
#if 0
struct iovec sg[2];
#else
uint8_t *buffer = NULL;
#endif
TRACE(TRACE_OSD, "osd_set_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Len %u)\n",
GroupID, UserID, page, n, len);
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_SET_ATTR;
args.GroupID = GroupID;
args.UserID = UserID;
args.length = 10 + len;
args.set_attributes_list_length = 10 + len;
*((uint32_t *) (list + 0)) = ISCSI_HTONL(page);
*((uint32_t *) (list + 4)) = ISCSI_HTONL(n);
*((uint16_t *) (list + 8)) = ISCSI_HTONS(len);
#if 0
sg[0].iov_base = list;
sg[0].iov_len = 10;
sg[1].iov_base = value;
sg[1].iov_len = len;
mem.send_data = sg;
mem.send_len = 10 + len;
mem.send_sg = 2;
#else
if ((buffer = iscsi_malloc_atomic(10 + len)) == NULL) {
TRACE_ERROR("iscsi_malloc() failed\n");
return -1;
}
memcpy(buffer, list, 10);
memcpy(buffer + 10, value, len);
mem.send_data = buffer;
mem.send_len = 10 + len;
mem.send_sg = 0;
#endif
mem.recv_data = NULL;
mem.recv_len = 0;
mem.recv_sg = 0;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
if (buffer)
iscsi_free_atomic(buffer);
return 0;
}
int
osd_get_one_attr(void *dev,
uint32_t GroupID, uint64_t UserID, uint32_t page, uint32_t n, uint32_t alloc_len,
int (*osd_exec) (void *dev, osd_args_t * args, OSD_OPS_MEM * mem),
uint16_t * len, void *value)
{
osd_args_t args;
OSD_OPS_MEM mem;
uint8_t list_out[8];
#if 0
uint8_t list_in[10];
struct iovec sg[2];
#else
uint8_t *buffer;
#endif
TRACE(TRACE_OSD, "osd_get_one_attr(GroupID 0x%x, UserID 0x%llx, Page 0x%x, Index %u, Alloc Len %u)\n",
GroupID, UserID, page, n, alloc_len);
memset(&args, 0, sizeof(osd_args_t));
args.opcode = 0x7F;
args.service_action = OSD_GET_ATTR;
args.GroupID = GroupID;
args.UserID = UserID;
if (n) {
args.length = 8;
*((uint32_t *) (list_out + 0)) = ISCSI_HTONL(page);
*((uint32_t *) (list_out + 4)) = ISCSI_HTONL(n);
args.get_attributes_list_length = 8;
mem.send_data = list_out;
mem.send_len = 8;
mem.send_sg = 0;
} else {
TRACE(TRACE_OSD, "requesting entire page or reference page\n");
mem.send_data = NULL;
mem.send_len = 0;
mem.send_sg = 0;
args.get_attributes_page = page;
}
#if 0
sg[0].iov_base = list_in;
sg[0].iov_len = 10;
sg[1].iov_base = value;
sg[1].iov_len = alloc_len;
mem.recv_data = sg;
mem.recv_len = 10 + alloc_len;
mem.recv_sg = 2;
#else
if ((buffer = iscsi_malloc_atomic(10 + alloc_len)) == NULL) {
TRACE_ERROR("iscsi_malloc() failed\n");
return -1;
}
mem.recv_data = buffer;
mem.recv_len = 10 + alloc_len;
mem.recv_sg = 0;
#endif
args.get_attributes_allocation_length = 10 + alloc_len;
if (osd_exec(dev, &args, &mem) != 0) {
TRACE_ERROR("osd_exec() failed\n");
return -1;
}
memcpy(value, buffer + 10, alloc_len);
if (buffer)
iscsi_free_atomic(buffer);
return 0;
}

1076
dist/iscsi/src/osdfs.c vendored Normal file

File diff suppressed because it is too large Load Diff

1276
dist/iscsi/src/parameters.c vendored Normal file

File diff suppressed because it is too large Load Diff

665
dist/iscsi/src/snprintf.c vendored Normal file
View File

@ -0,0 +1,665 @@
/*
* Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* From heimdal lib/roken/snprintf.c. */
#include "config.h"
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#if 0
RCSID("$Id: snprintf.c,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $");
#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if 0
#include <roken.h>
#endif
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))
enum format_flags {
minus_flag = 1,
plus_flag = 2,
space_flag = 4,
alternate_flag = 8,
zero_flag = 16
};
/*
* Common state
*/
struct state {
unsigned char *str;
unsigned char *s;
unsigned char *theend;
size_t sz;
size_t max_sz;
void (*append_char)(struct state *, unsigned char);
/* XXX - methods */
};
#if TEST_SNPRINTF
#include "snprintf-test.h"
#endif /* TEST_SNPRINTF */
#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
static int
sn_reserve (struct state *state, size_t n)
{
return state->s + n > state->theend;
}
static void
sn_append_char (struct state *state, unsigned char c)
{
if (!sn_reserve (state, 1))
*state->s++ = c;
}
#endif
static int
as_reserve (struct state *state, size_t n)
{
if (state->s + n > state->theend) {
int off = state->s - state->str;
unsigned char *tmp;
if (state->max_sz && state->sz >= state->max_sz)
return 1;
state->sz = max(state->sz * 2, state->sz + n);
if (state->max_sz)
state->sz = min(state->sz, state->max_sz);
tmp = realloc (state->str, state->sz);
if (tmp == NULL)
return 1;
state->str = tmp;
state->s = state->str + off;
state->theend = state->str + state->sz - 1;
}
return 0;
}
static void
as_append_char (struct state *state, unsigned char c)
{
if(!as_reserve (state, 1))
*state->s++ = c;
}
/* longest integer types */
#ifdef HAVE_LONG_LONG
typedef unsigned long long u_longest;
typedef long long longest;
#else
typedef unsigned long u_longest;
typedef long longest;
#endif
/*
* is # supposed to do anything?
*/
static int
use_alternative (int flags, u_longest num, unsigned base)
{
return flags & alternate_flag && (base == 16 || base == 8) && num != 0;
}
static int
append_number(struct state *state,
u_longest num, unsigned base, char *rep,
int width, int prec, int flags, int minusp)
{
int len = 0;
int i;
u_longest n = num;
/* given precision, ignore zero flag */
if(prec != -1)
flags &= ~zero_flag;
else
prec = 1;
/* zero value with zero precision -> "" */
if(prec == 0 && n == 0)
return 0;
do{
(*state->append_char)(state, rep[n % base]);
++len;
n /= base;
} while(n);
prec -= len;
/* pad with prec zeros */
while(prec-- > 0){
(*state->append_char)(state, '0');
++len;
}
/* add length of alternate prefix (added later) to len */
if(use_alternative(flags, num, base))
len += base / 8;
/* pad with zeros */
if(flags & zero_flag){
width -= len;
if(minusp || (flags & space_flag) || (flags & plus_flag))
width--;
while(width-- > 0){
(*state->append_char)(state, '0');
len++;
}
}
/* add alternate prefix */
if(use_alternative(flags, num, base)){
if(base == 16)
(*state->append_char)(state, rep[10] + 23); /* XXX */
(*state->append_char)(state, '0');
}
/* add sign */
if(minusp){
(*state->append_char)(state, '-');
++len;
} else if(flags & plus_flag) {
(*state->append_char)(state, '+');
++len;
} else if(flags & space_flag) {
(*state->append_char)(state, ' ');
++len;
}
if(flags & minus_flag)
/* swap before padding with spaces */
for(i = 0; i < len / 2; i++){
char c = state->s[-i-1];
state->s[-i-1] = state->s[-len+i];
state->s[-len+i] = c;
}
width -= len;
while(width-- > 0){
(*state->append_char)(state, ' ');
++len;
}
if(!(flags & minus_flag))
/* swap after padding with spaces */
for(i = 0; i < len / 2; i++){
char c = state->s[-i-1];
state->s[-i-1] = state->s[-len+i];
state->s[-len+i] = c;
}
return len;
}
/*
* return length
*/
static int
append_string (struct state *state,
const unsigned char *arg,
int width,
int prec,
int flags)
{
int len = 0;
if(arg == NULL)
arg = (const unsigned char*)"(null)";
if(prec != -1)
width -= prec;
else
width -= strlen((const char *)arg);
if(!(flags & minus_flag))
while(width-- > 0) {
(*state->append_char) (state, ' ');
++len;
}
if (prec != -1) {
while (*arg && prec--) {
(*state->append_char) (state, *arg++);
++len;
}
} else {
while (*arg) {
(*state->append_char) (state, *arg++);
++len;
}
}
if(flags & minus_flag)
while(width-- > 0) {
(*state->append_char) (state, ' ');
++len;
}
return len;
}
static int
append_char(struct state *state,
unsigned char arg,
int width,
int flags)
{
int len = 0;
while(!(flags & minus_flag) && --width > 0) {
(*state->append_char) (state, ' ') ;
++len;
}
(*state->append_char) (state, arg);
++len;
while((flags & minus_flag) && --width > 0) {
(*state->append_char) (state, ' ');
++len;
}
return 0;
}
/*
* This can't be made into a function...
*/
#ifdef HAVE_LONG_LONG
#define PARSE_INT_FORMAT(res, arg, unsig) \
if (long_long_flag) \
res = (unsig long long)va_arg(arg, unsig long long); \
else if (long_flag) \
res = (unsig long)va_arg(arg, unsig long); \
else if (short_flag) \
res = (unsig short)va_arg(arg, unsig int); \
else \
res = (unsig int)va_arg(arg, unsig int)
#else
#define PARSE_INT_FORMAT(res, arg, unsig) \
if (long_flag) \
res = (unsig long)va_arg(arg, unsig long); \
else if (short_flag) \
res = (unsig short)va_arg(arg, unsig int); \
else \
res = (unsig int)va_arg(arg, unsig int)
#endif
/*
* zyxprintf - return length, as snprintf
*/
static int
xyzprintf (struct state *state, const char *char_format, va_list ap)
{
const unsigned char *format = (const unsigned char *)char_format;
unsigned char c;
int len = 0;
while((c = *format++)) {
if (c == '%') {
int flags = 0;
int width = 0;
int prec = -1;
int long_long_flag = 0;
int long_flag = 0;
int short_flag = 0;
/* flags */
while((c = *format++)){
if(c == '-')
flags |= minus_flag;
else if(c == '+')
flags |= plus_flag;
else if(c == ' ')
flags |= space_flag;
else if(c == '#')
flags |= alternate_flag;
else if(c == '0')
flags |= zero_flag;
else
break;
}
if((flags & space_flag) && (flags & plus_flag))
flags ^= space_flag;
if((flags & minus_flag) && (flags & zero_flag))
flags ^= zero_flag;
/* width */
if (isdigit(c))
do {
width = width * 10 + c - '0';
c = *format++;
} while(isdigit(c));
else if(c == '*') {
width = va_arg(ap, int);
c = *format++;
}
/* precision */
if (c == '.') {
prec = 0;
c = *format++;
if (isdigit(c))
do {
prec = prec * 10 + c - '0';
c = *format++;
} while(isdigit(c));
else if (c == '*') {
prec = va_arg(ap, int);
c = *format++;
}
}
/* size */
if (c == 'h') {
short_flag = 1;
c = *format++;
} else if (c == 'l') {
long_flag = 1;
c = *format++;
if (c == 'l') {
long_long_flag = 1;
c = *format++;
}
}
switch (c) {
case 'c' :
append_char(state, va_arg(ap, int), width, flags);
++len;
break;
case 's' :
len += append_string(state,
va_arg(ap, unsigned char*),
width,
prec,
flags);
break;
case 'd' :
case 'i' : {
longest arg;
u_longest num;
int minusp = 0;
PARSE_INT_FORMAT(arg, ap, signed);
if (arg < 0) {
minusp = 1;
num = -arg;
} else
num = arg;
len += append_number (state, num, 10, "0123456789",
width, prec, flags, minusp);
break;
}
case 'u' : {
u_longest arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
len += append_number (state, arg, 10, "0123456789",
width, prec, flags, 0);
break;
}
case 'o' : {
u_longest arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
len += append_number (state, arg, 010, "01234567",
width, prec, flags, 0);
break;
}
case 'x' : {
u_longest arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
len += append_number (state, arg, 0x10, "0123456789abcdef",
width, prec, flags, 0);
break;
}
case 'X' :{
u_longest arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
len += append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0);
break;
}
case 'p' : {
unsigned long arg = (unsigned long)va_arg(ap, void*);
len += append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0);
break;
}
case 'n' : {
int *arg = va_arg(ap, int*);
*arg = state->s - state->str;
break;
}
case '\0' :
--format;
/* FALLTHROUGH */
case '%' :
(*state->append_char)(state, c);
++len;
break;
default :
(*state->append_char)(state, '%');
(*state->append_char)(state, c);
len += 2;
break;
}
} else {
(*state->append_char) (state, c);
++len;
}
}
return len;
}
#if !defined(HAVE_SNPRINTF) || defined(TEST_SNPRINTF)
int
snprintf (char *str, size_t sz, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vsnprintf (str, sz, format, args);
va_end(args);
#ifdef PARANOIA
{
int ret2;
char *tmp;
tmp = malloc (sz);
if (tmp == NULL)
abort ();
va_start(args, format);
ret2 = vsprintf (tmp, format, args);
va_end(args);
if (ret != ret2 || strcmp(str, tmp))
abort ();
free (tmp);
}
#endif
return ret;
}
#endif
#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF)
int
asprintf (char **ret, const char *format, ...)
{
va_list args;
int val;
va_start(args, format);
val = vasprintf (ret, format, args);
#ifdef PARANOIA
{
int ret2;
char *tmp;
tmp = malloc (val + 1);
if (tmp == NULL)
abort ();
ret2 = vsprintf (tmp, format, args);
if (val != ret2 || strcmp(*ret, tmp))
abort ();
free (tmp);
}
#endif
va_end(args);
return val;
}
#endif
#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF)
int
asnprintf (char **ret, size_t max_sz, const char *format, ...)
{
va_list args;
int val;
va_start(args, format);
val = vasnprintf (ret, max_sz, format, args);
#ifdef PARANOIA
{
int ret2;
char *tmp;
tmp = malloc (val + 1);
if (tmp == NULL)
abort ();
ret2 = vsprintf (tmp, format, args);
if (val != ret2 || strcmp(*ret, tmp))
abort ();
free (tmp);
}
#endif
va_end(args);
return val;
}
#endif
#if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF)
int
vasprintf (char **ret, const char *format, va_list args)
{
return vasnprintf (ret, 0, format, args);
}
#endif
#if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF)
int
vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
{
int st;
struct state state;
state.max_sz = max_sz;
state.sz = 1;
state.str = malloc(state.sz);
if (state.str == NULL) {
*ret = NULL;
return -1;
}
state.s = state.str;
state.theend = state.s + state.sz - 1;
state.append_char = as_append_char;
st = xyzprintf (&state, format, args);
if (st > state.sz) {
free (state.str);
*ret = NULL;
return -1;
} else {
char *tmp;
*state.s = '\0';
tmp = realloc (state.str, st+1);
if (tmp == NULL) {
free (state.str);
*ret = NULL;
return -1;
}
*ret = tmp;
return st;
}
}
#endif
#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
int
vsnprintf (char *str, size_t sz, const char *format, va_list args)
{
struct state state;
int ret;
unsigned char *ustr = (unsigned char *)str;
state.max_sz = 0;
state.sz = sz;
state.str = ustr;
state.s = ustr;
state.theend = ustr + sz - (sz > 0);
state.append_char = sn_append_char;
ret = xyzprintf (&state, format, args);
if (state.s != NULL)
*state.s = '\0';
return ret;
}
#endif

1060
dist/iscsi/src/so.c vendored Normal file

File diff suppressed because it is too large Load Diff

5
dist/iscsi/src/start_osd vendored Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
insmod ./so.o
insmod ./intel_iscsi.o
insmod ./osdfs.o
mount -t osdfs /dev/so0 /mnt -o gid=0x2d159c01 -o uid=0x2c8f1801

5
dist/iscsi/src/stop_osd vendored Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
umount /mnt
rmmod osdfs
rmmod intel_iscsi
rmmod so

88
dist/iscsi/src/strlcpy.c vendored Normal file
View File

@ -0,0 +1,88 @@
/* $NetBSD: strlcpy.c,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $ */
/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#if !defined(_KERNEL) && !defined(_STANDALONE)
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: strlcpy.c,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $");
#endif /* LIBC_SCCS and not lint */
#ifdef _LIBC
#include "namespace.h"
#endif
#include <sys/types.h>
#include <assert.h>
#include <string.h>
#ifdef _LIBC
# ifdef __weak_alias
__weak_alias(strlcpy, _strlcpy)
# endif
#endif
#else
#include <lib/libkern/libkern.h>
#endif /* !_KERNEL && !_STANDALONE */
#if !HAVE_STRLCPY
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
#ifdef _LIBC
_strlcpy(dst, src, siz)
#else
strlcpy(dst, src, siz)
#endif
char *dst;
const char *src;
size_t siz;
{
char *d = dst;
const char *s = src;
size_t n = siz;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(src != NULL);
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
#endif

70
dist/iscsi/src/strtoll.c vendored Normal file
View File

@ -0,0 +1,70 @@
/* $NetBSD: strtoll.c,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Alistair Crooks
* for the NetBSD project.
* 4. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright © 2006 \
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: strtoll.c,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $");
#endif
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "compat.h"
#ifndef HAVE_STRTOLL
static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
int64_t
strtoll(const char *ptr, const char **endptr, int base)
{
const char *cp;
int64_t ret;
char *dig;
int d;
for (ret = 0, cp = ptr ; *cp && (dig = strchr(digits, *cp)) != NULL && (d = (int)(dig - digits)) < base ; cp++) {
ret = (ret * base) + d;
}
if (endptr != NULL) {
*endptr = cp;
}
return ret;
}
#endif /* HAVE_STRTOLL */

1584
dist/iscsi/src/target.c vendored Normal file

File diff suppressed because it is too large Load Diff

20
dist/iscsi/src/targets vendored Normal file
View File

@ -0,0 +1,20 @@
# Structure of this file:
#
# + an extent is a straight (offset, length) pair of a file or device
# it's the lowest common storage denominator
# at least one is needed
# + a device is made up of one or more extents or other devices
# devices can be added in a hierachical manner, to enhance resilience
# + in this example, no device definitions are necessary, as the target
# will just use a simple extent for persistent storage
# + a target is made up of 1 or more devices
#
# The code does not support RAID1 recovery at present
# Simple file showing 1 extent, and 1 target
# extents
extent0 /tmp/iscsi-target0 0 100MB
# targets
target0 extent0 10.4.0.0/16

148
dist/iscsi/src/targets.5 vendored Normal file
View File

@ -0,0 +1,148 @@
.\" $NetBSD: targets.5,v 1.1.1.1 2006/02/08 18:56:20 agc Exp $
.\"
.\" Copyright © 2006 Alistair Crooks. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 30, 2006
.Dt TARGETS 5
.Os
.Sh NAME
.Nm targets
.Nd configuration file for iSCSI targets
.Sh SYNOPSIS
.Nm targets
.Sh DESCRIPTION
The
.Nm
file describes the iSCSI storage which is presented to iSCSI
initiators by the
.Xr iscsi-target 8
service.
A description of the iSCSI protocol can be found in
.%T "Internet Small Computer Systems Interface \\*(tNRFC\\*(sP 3720" .
.Pp
Each line in the file
(other than comment lines that begin with a
.Sq # )
specifies an extent, a device (made up of extents or other devices),
or a target to present to the initiator.
.Pp
Each definition, an extent, a device, and a target, is specified
on a single whitespace delimited line.
.Pp
The
.Ar extent
definition specifies a piece of storage that will be used
as storage, and presented to initiators.
It is the basic definition for an iSCSI target.
Each target must contain at least one extent definition.
The first field in the definition is the extent name, which must
begin with the word
.Dq extent
and be followed by a number.
The next field is the file or
.Nx
device which will be used as persistent storage.
The next field is the offset (in bytes) of the start of the extent.
This field is usually 0.
The fourth field in the definition is the size of the extent.
The basic unit is bytes, and the shorthand
.Ar KB ,
.Ar MB ,
.Ar GB ,
and
.Ar TB
can be used for kilobytes (1024 bytes),
megabytes (1024 kilobytes), gigabytes
(1024 megabytes), and
terabytes (1024 gigabytes) respectively.
.Pp
The
.Ar device
definition specifies a LUN or device, and is made up of extents
and other devices.
It is possible to create hierarchies of devices using the device definition.
The first field in the definition is the device name, which must
begin with the word
.Dq device
and be followed by a number.
The next field is the type of resilience that is to be provided
by the device.
For simple devices,
.Ar RAID0
suffices.
Greater resilience can be gained by using the
.Ar RAID1
resilience field.
Following the resilience field is a list of extents or other devices.
Large devices can be created by using multiple RAID0 extents,
in which case each extent will be concatenated.
Resilient devices can be created by using multiple RAID1 devices
or extents, in which case data will be written to each of the
devices or extents in turn.
If RAID1 resilience is used, all the extents or sub-devices must
be the same size.
Please note that RAID1 recovery is not yet supported by the
.Xr iscsi-target 8
utility.
An extent or sub-device may only be used once.
.Pp
The
.Ar target
definition specifies an iSCSI target, which is presented to the iSCSI
initiator.
Multiple targets can be specified.
The first field in the definition is the target name, which must
begin with the word
.Dq target
and be followed by a number.
The next field is the device or extent name that will be used as persistent storage
for this target.
The third field is a slash-notation netmask which will be used, during the
discovery phase, to control the network addresses to which targets will
be presented.
Please note that this netmask functionality has not yet been implemented,
and so
tcp wrapper functionality, as found in
.Xr hosts_access 5
and
.Xr hosts.deny 5
should be used at present.
.Sh FILES
.Bl -tag -width /etc/iscsi/targets -compact
.It Pa /etc/iscsi/targets
the list of exported storage
.Nm
.El
.Sh SEE ALSO
.Xr hosts_access 5 ,
.Xr hosts.deny 5 ,
.Xr iscsi-target 8
.Sh HISTORY
The
.Nm
file first appeared in
.Nx 4.0 .

1336
dist/iscsi/src/tests.c vendored Normal file

File diff suppressed because it is too large Load Diff

378
dist/iscsi/src/usocktest.c vendored Normal file
View File

@ -0,0 +1,378 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define EXTERN
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include "util.h"
/*
* NOTE: THIS IS A WORK IN PROGRESS.
*
* For now, you must manually enter the host and target send and recv patterns
* (shown in the code below) beginning at line 104. By default, this code will
* simulate the TCP traffic generated by an 8K iSCSI read between host and target.
*/
#define NUM_ITERS_DEFAULT 200
#define VERBOSE_FREQ_DEFAULT 20
#define PORT_DEFAULT 5001
#define HOST_SEND_PATTERN_DEFAULT "48" /* send iSCSI command PDU (SCSI READ) */
#define TARG_RECV_PATTERN_DEFAULT "48"
#define TARG_SEND_PATTERN_DEFAULT "48+8192" /* phase collapsed 8K data + status */
#define HOST_RECV_PATTERN_DEFAULT "48+8192"
/*
* Constants
*/
#define toSeconds(t) (t.tv_sec + (t.tv_usec/1000000.))
#define MAX_PATTERN_LEN 1024
#define MAX_BUFFS MAX_PATTERN_LEN/2
char usage[] = "usage: -t <target IP> I/O target\n"
" -hsp <host send pattern> e.g., 48\n"
" -tsp <targ recv pattern> e.g., 48\n"
" -hsp <targ repl pattern> e.g.. 8240\n"
" -hsp <host recv pattern> e.g., 48+8192\n"
" -n <num iter> number of iterations\n"
" -v <freq> verbose mode\n"
" -p <port> port number\n"
"\nNOTE: The pattern args are not yet implemented.\n"
" You must manually edit usocktest.c to change\n"
" the request pattern which, by default, generates\n"
" TCP traffic identical to an 32 MB iSCSI read\n"
" that uses 8KB data PDUs.\n";
int main(int argc, char *argv[]) {
int i, j, n;
char HostSendPattern[MAX_PATTERN_LEN];
char HostRecvPattern[MAX_PATTERN_LEN];
char TargSendPattern[MAX_PATTERN_LEN];
char TargRecvPattern[MAX_PATTERN_LEN];
int HostSendSize[MAX_BUFFS];
int HostRecvSize[MAX_BUFFS];
int TargSendSize[MAX_BUFFS];
int TargRecvSize[MAX_BUFFS];
unsigned char* HostSendBuff[MAX_BUFFS];
unsigned char* HostRecvBuff[MAX_BUFFS];
unsigned char* TargSendBuff[MAX_BUFFS];
unsigned char* TargRecvBuff[MAX_BUFFS];
int NumHostSendBuffs;
int NumHostRecvBuffs;
int NumTargSendBuffs;
int NumTargRecvBuffs;
char ctrlBufferSend[MAX_PATTERN_LEN];
char ctrlBufferRecv[MAX_PATTERN_LEN];
unsigned ctrlBuffSize = MAX_PATTERN_LEN;
struct timeval t_start, t_stop;
double time;
iscsi_socket_t iscsi_sock, iscsi_sock_new;
int HostSendTotal, HostRecvTotal;
int TargRecvTotal, TargSendTotal;
int IsTarget;
int Port = PORT_DEFAULT;
int NumIters = NUM_ITERS_DEFAULT;
int VerboseFreq = VERBOSE_FREQ_DEFAULT;
char TargetIP[64] = "";
/*
* Parse command line
*/
strcpy(HostSendPattern, HOST_SEND_PATTERN_DEFAULT);
strcpy(HostRecvPattern, HOST_RECV_PATTERN_DEFAULT);
strcpy(TargSendPattern, TARG_SEND_PATTERN_DEFAULT);
strcpy(TargRecvPattern, TARG_RECV_PATTERN_DEFAULT);
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-t")) {
i++; strcpy(TargetIP, argv[i]);
} else if (!strcmp(argv[i], "-p")) {
i++; sscanf(argv[i], "%u", &Port);
} else if (!strcmp(argv[i], "-n")) {
i++; sscanf(argv[i], "%u", &NumIters);
} else if (!strcmp(argv[i], "-v")) {
i++; sscanf(argv[i], "%u", &VerboseFreq);
} else {
PRINT("Unknown option \"%s\"\n", argv[i]);
PRINT("%s\n", usage);
return -1;
}
}
if (argc == 1) PRINT("%s\n", usage);
IsTarget = (strlen(TargetIP)>0)?0:1;
/*
* Convert command line string patterns here. For now, you must
* manually enter these below.
*/
NumHostSendBuffs = 1;
HostSendSize[0] = 48;
NumTargRecvBuffs = 1;
TargRecvSize[0] = 48;
NumHostRecvBuffs = 2;
HostRecvSize[0] = 48;
HostRecvSize[1] = 524288;
NumTargSendBuffs = 2;
TargSendSize[0] = 48;
TargSendSize[1] = 524288;
/*
* Create/bind/listen
*/
if (iscsi_sock_create(&iscsi_sock)!=0) {
TRACE_ERROR("iscsi_sock_create() failed\n");
return -1;
}
if (IsTarget) {
if (iscsi_sock_bind(iscsi_sock, Port)!=0) {
TRACE_ERROR("iscsi_sock_bind() failed\n");
return -1;
}
if (iscsi_sock_listen(iscsi_sock)!=0) {
TRACE_ERROR("iscsi_sock_listen() failed\n");
return -1;
}
}
/*
* Accept connection
*/
accept:
if (IsTarget) {
PRINT("Waiting for TCP connection on port %u\n", Port);
if(iscsi_sock_accept(iscsi_sock, &iscsi_sock_new)!=0) {
TRACE_ERROR("iscsi_sock_accept() failed\n");
return -1;
}
PRINT("Connection accepted\n");
} else {
printf("Connecting to %s\n", TargetIP);
if(iscsi_sock_connect(iscsi_sock, TargetIP, Port)!=0) {
TRACE_ERROR("iscsi_sock_connect() failed\n");
return -1;
}
PRINT("Connected\n");
iscsi_sock_new = iscsi_sock;
}
/*
* Host/Target handshake for test parameters
*/
if (!IsTarget) {
TRACE(TRACE_DEBUG, "Sending test parameters\n");
sprintf(ctrlBufferSend, "%s:%s:%s:%s:%i:%i:%i",
HostSendPattern, HostRecvPattern, TargSendPattern, TargRecvPattern,
NumIters, VerboseFreq, Port);
if ((n=iscsi_sock_msg(iscsi_sock_new, 1, ctrlBuffSize, ctrlBufferSend, 0))!=ctrlBuffSize) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
if ((n=iscsi_sock_msg(iscsi_sock_new, 0, ctrlBuffSize, ctrlBufferRecv, 0))!=ctrlBuffSize) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Test parameters sent\n");
} else {
char *ptr, *delim;
TRACE(TRACE_DEBUG, "Receiving test parameters\n");
if ((n=iscsi_sock_msg(iscsi_sock_new, 0, ctrlBuffSize, ctrlBufferRecv, 0))!=ctrlBuffSize) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
ptr = ctrlBufferRecv;
delim = strchr(ptr, ':');
strncpy(HostSendPattern, ptr, delim-ptr+1); HostSendPattern[delim-ptr] = 0x0; ptr = delim+1;
delim = strchr(ptr, ':');
strncpy(HostRecvPattern, ptr, delim-ptr+1); HostRecvPattern[delim-ptr] = 0x0; ptr = delim+1;
delim = strchr(ptr, ':');
strncpy(TargSendPattern, ptr, delim-ptr+1); TargSendPattern[delim-ptr] = 0x0; ptr = delim+1;
delim = strchr(ptr, ':');
strncpy(TargRecvPattern, ptr, delim-ptr+1); TargRecvPattern[delim-ptr] = 0x0; ptr = delim+1;
sscanf(ptr, "%i:%i", &NumIters, &VerboseFreq);
if ((n=iscsi_sock_msg(iscsi_sock_new, 1, ctrlBuffSize, ctrlBufferSend, 0))!=ctrlBuffSize) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Test parameters received\n");
}
/*
* Check Arguments
*/
HostSendTotal = 0; for (i=0; i<NumHostSendBuffs; i++) HostSendTotal += HostSendSize[i];
TargRecvTotal = 0; for (i=0; i<NumTargRecvBuffs; i++) TargRecvTotal += TargRecvSize[i];
if (HostSendTotal != TargRecvTotal) {
TRACE_ERROR("Host sending size (%i) > Target receiving size (%i)\n",
HostSendTotal, TargRecvTotal);
return -1;
}
HostRecvTotal = 0; for (i=0; i<NumHostRecvBuffs; i++) HostRecvTotal += HostRecvSize[i];
TargSendTotal = 0; for (i=0; i<NumTargSendBuffs; i++) TargSendTotal += TargSendSize[i];
if (HostRecvTotal != TargSendTotal) {
TRACE_ERROR("Host receiving size (%i) > Target sending size (%i)\n",
HostRecvTotal, TargSendTotal);
return -1;
}
TRACE(TRACE_DEBUG, "HostSendPattern: \"%s\"\n", HostSendPattern);
TRACE(TRACE_DEBUG, "HostRecvPattern: \"%s\"\n", HostRecvPattern);
TRACE(TRACE_DEBUG, "TargRecvPattern: \"%s\"\n", TargRecvPattern);
TRACE(TRACE_DEBUG, "TargSendPattern: \"%s\"\n", TargSendPattern);
TRACE(TRACE_DEBUG, "NumIters: %i\n", NumIters);
TRACE(TRACE_DEBUG, "VerboseFreq: %i\n", VerboseFreq);
TRACE(TRACE_DEBUG, "HostSendTotal: %i bytes\n", HostSendTotal);
TRACE(TRACE_DEBUG, "HostRecvTotal: %i bytes\n", HostRecvTotal);
/*
* Allocate buffers
*/
for (i=0; i<NumHostSendBuffs; i++)
if ((HostSendBuff[i]=iscsi_malloc(HostSendSize[i]))==NULL) {
TRACE_ERROR("out of memory\n");
return -1;
}
for (i=0; i<NumHostRecvBuffs; i++)
if ((HostRecvBuff[i]=iscsi_malloc(HostRecvSize[i]))==NULL) {
TRACE_ERROR("out of memory\n");
return -1;
}
for (i=0; i<NumTargSendBuffs; i++)
if ((TargSendBuff[i]=iscsi_malloc(TargSendSize[i]))==NULL) {
TRACE_ERROR("out of memory\n");
return -1;
}
for (i=0; i<NumTargRecvBuffs; i++)
if ((TargRecvBuff[i]=iscsi_malloc(TargRecvSize[i]))==NULL) {
TRACE_ERROR("out of memory\n");
return -1;
}
/*
* Begin I/O
*/
gettimeofday(&t_start, 0);
for (i=0; i<NumIters; i++) {
TRACE(TRACE_DEBUG, "begin iteration %i\n", i);
if (!IsTarget) {
/* Send to target */
for (j=0; j<NumHostSendBuffs; j++) {
if (iscsi_sock_msg(iscsi_sock_new, 1, HostSendSize[j], HostSendBuff[j], 0)!= HostSendSize[j]) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Tx HostSendBuff[%i] (size %i)\n", j, HostSendSize[j]);
}
/* Recv from target */
for (j=0; j<NumHostRecvBuffs; j++) {
if (iscsi_sock_msg(iscsi_sock_new, 0, HostRecvSize[j], HostRecvBuff[j], 0)!= HostRecvSize[j]) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Rx HostRecvBuff[%i] (size %i)\n", j, HostRecvSize[j]);
}
} else {
/* Recv from host */
for (j=0; j<NumTargRecvBuffs; j++) {
if (iscsi_sock_msg(iscsi_sock_new, 0, TargRecvSize[j], TargRecvBuff[j], 0)!= TargRecvSize[j]) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Rx TargRecvBuff[%i] (size %i)\n", j, TargRecvSize[j]);
}
/* Send to host */
for (j=0; j<NumTargSendBuffs; j++) {
if (iscsi_sock_msg(iscsi_sock_new, 1, TargSendSize[j], TargSendBuff[j], 0)!= TargSendSize[j]) {
TRACE_ERROR("iscsi_sock_msg() failed\n");
return -1;
}
TRACE(TRACE_DEBUG, "Tx TargSendBuff[%i] (size %i)\n", j, TargSendSize[j]);
}
}
if ((!IsTarget)&&((i+1)%VerboseFreq==0)) {
PRINT("Iter %i: %i total bytes sent, %i total bytes recv\n",
i+1, HostSendTotal*(i+1), HostRecvTotal*(i+1));
}
TRACE(TRACE_DEBUG, "end iteration %i\n", i);
}
gettimeofday(&t_stop, 0);
/*
* End I/O
*/
/* Free buffers */
for (i=0; i<NumHostSendBuffs; i++) iscsi_free(HostSendBuff[i]);
for (i=0; i<NumHostRecvBuffs; i++) iscsi_free(HostRecvBuff[i]);
for (i=0; i<NumTargSendBuffs; i++) iscsi_free(TargSendBuff[i]);
for (i=0; i<NumTargRecvBuffs; i++) iscsi_free(TargRecvBuff[i]);
/* Output stats */
if (IsTarget) {
goto accept;
} else {
time = (double) (toSeconds(t_stop) - toSeconds(t_start));
printf("Send Size: %i bytes\n", HostSendTotal);
printf("Recv Size: %i bytes\n", HostRecvTotal);
printf("Num Iters: %i\n", NumIters);
printf("Elapsed Time: %.4f sec\n", time);
printf("Avg RT Latency: %.2f usec\n", (time*1000000/NumIters));
printf("Send Performance: %.2f MB/sec sec\n", ((HostSendTotal*NumIters)/time)/1048576);
printf("Recv Performance: %.2f MB/sec sec\n", ((HostRecvTotal*NumIters)/time)/1048576);
}
return 0;
}

158
dist/iscsi/src/utest.c vendored Normal file
View File

@ -0,0 +1,158 @@
/*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
* using the software you agree to this license. If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Intel License Agreement
*
* Copyright (c) 2000, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
*
* -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* -The name of Intel Corporation may not be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define EXTERN
#include <sys/types.h>
#include <sys/param.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <unistd.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include "scsi_cmd_codes.h"
#include "iscsi.h"
#include "initiator.h"
#include "tests.h"
int
mycallback(void *arg)
{
(*((int *) arg))++;
return 0;
}
int
main(int argc, char *argv[])
{
struct sigaction act;
char hostname[1024];
char *host;
int tgtlo = 0;
int tgthi = CONFIG_INITIATOR_NUM_TARGETS;
int target = -1;
int lun = 0;
int i, j;
int iterations;
/* Check args */
iterations = 1;
(void) gethostname(host = hostname, sizeof(hostname));
while ((i = getopt(argc, argv, "h:l:n:t:")) != -1) {
switch(i) {
case 'h':
host = optarg;
break;
case 'l':
lun = atoi(optarg);
break;
case 'n':
iterations = atoi(optarg);
break;
case 't':
target = atoi(optarg);
break;
default:
(void) fprintf(stderr, "%s: unknown option `%c'", *argv, i);
}
}
if (target != -1) {
if (target >= CONFIG_INITIATOR_NUM_TARGETS) {
TRACE_ERROR("initiator only configured with %i targets\n", CONFIG_INITIATOR_NUM_TARGETS);
exit(EXIT_FAILURE);
}
tgtlo = target;
tgthi = target + 1;
}
if (argc == 1) {
(void) fprintf(stderr, "usage: %s [-h hostname] [-l lun] [-n iterations] [-t target]\n", *argv);
exit(EXIT_FAILURE);
}
for (j = 0; j < iterations; j++) {
PRINT("<ITERATION %i>\n", j);
/* Ignore sigpipe */
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
/* Initialize Initiator */
if (initiator_init(host) == -1) {
TRACE_ERROR("initiator_init() failed\n");
return -1;
}
/* Run tests for each target */
for (i = tgtlo; i < tgthi; i++) {
if (test_all(i, lun) != 0) {
TRACE_ERROR("test_all() failed\n");
return -1;
}
}
/* Shutdown Initiator */
if (initiator_shutdown() == -1) {
TRACE_ERROR("initiator_shutdown() failed\n");
return -1;
}
}
printf("\n");
printf("************************************\n");
printf("* ALL TESTS COMPLETED SUCCESSFULLY *\n");
printf("************************************\n");
printf("\n");
exit(EXIT_SUCCESS);
}

1011
dist/iscsi/src/util.c vendored Normal file

File diff suppressed because it is too large Load Diff