summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorzl149053 <none@none>2008-07-07 22:47:28 -0700
committerzl149053 <none@none>2008-07-07 22:47:28 -0700
commit3e55d14bd284a989ba645bc1558916a474881701 (patch)
treeceb10a9b0f8ef3a37765ee0bbe1443866df6d5dc /usr/src
parent0bdffa0f07e70f45f6810116ca9d547631a4c3f8 (diff)
downloadillumos-joyent-3e55d14bd284a989ba645bc1558916a474881701.tar.gz
6718269 single target with dual luns does not work with VMWare ESX
6721787 iscsitgtd should use IEEE company id to compose guid 6722522 cannot correctly discover zvol iscsi targets with vmware esx iscsi initiator (2)
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sam.c6
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc.c53
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/target.h38
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/util.c109
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/utility.h2
-rw-r--r--usr/src/lib/libiscsitgt/common/xml.c3
6 files changed, 176 insertions, 35 deletions
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
index 937814794c..fb3d59ea05 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
@@ -1545,7 +1545,11 @@ t10_find_lun(t10_targ_impl_t *t, int lun, t10_cmd_t *cmd)
if ((strcmp(guid, "0") == 0) || (strcmp(guid, "0x0") == 0)) {
free(guid);
- if (util_create_guid(&guid) == False) {
+ /*
+ * Create the GUID with NAA IEEE Registered Extended
+ * designator format.
+ */
+ if (util_create_guid(&guid, SPC_INQUIRY_ID_TYPE_NAA) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c
index 65df89d597..a175b88ef5 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c
@@ -40,6 +40,7 @@
#include <sys/param.h>
#include <strings.h>
#include <unistd.h>
+#include <assert.h>
#include <sys/scsi/generic/sense.h>
#include <sys/scsi/generic/status.h>
@@ -51,8 +52,6 @@
#include "t10_spc.h"
#include "target.h"
-#define VMWARE_I_NAME "iqn.1998-01.com.vmware"
-
void spc_free(emul_handle_t id);
/*
@@ -138,6 +137,7 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
{
uint8_t *rsp_buf;
uint8_t *rbp; /* temporary var */
+ uint8_t evpd;
struct scsi_inquiry *inq;
uint32_t len;
uint32_t page83_len;
@@ -162,8 +162,15 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
* (2) If any bit other than EVPD is set.
* (3) If any of the reserved bits in the CONTROL byte are set.
*/
- if (((cdb[1] == 0) && (cdb[2] != 0)) || (cdb[1] & ~1) ||
- SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
+ /*
+ * SPC-3,4 keyword reserved:
+ * ...Receipts are not required to check reserved bits, bytes, words
+ * or fields for zero values.
+ *
+ * Ignore the check for reserved fields in the CDB byte 1.
+ */
+ evpd = cdb[1] & 1;
+ if ((evpd == 0 && (cdb[2] != 0)) || SAM_CONTROL_BYTE_RESERVED(cdb[5])) {
spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
trans_send_complete(cmd, STATUS_CHECK);
@@ -213,7 +220,7 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
/*
* EVPD not set returns the standard inquiry data.
*/
- if (cdb[1] == 0) {
+ if (evpd == 0) {
/*
* Return whatever is the smallest amount between the
* INQUIRY data or the amount requested.
@@ -321,23 +328,11 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
* page length as defined by (n - 3) where 'n' is
* the last valid byte. In this case 5.
*/
- /*
- * do not provide inquiry of page 80 for vmware
- * iscsi initiator, see CR 6597310.
- */
- if (strncmp(cmd->c_lu->l_targ->s_i_name,
- VMWARE_I_NAME, strlen(VMWARE_I_NAME)) != 0) {
- rsp_buf[3] = 4;
- rsp_buf[4] = SPC_INQ_PAGE0;
- rsp_buf[5] = SPC_INQ_PAGE80;
- rsp_buf[6] = SPC_INQ_PAGE83;
- rsp_buf[7] = SPC_INQ_PAGE86;
- } else {
- rsp_buf[3] = 3;
- rsp_buf[4] = SPC_INQ_PAGE0;
- rsp_buf[5] = SPC_INQ_PAGE83;
- rsp_buf[6] = SPC_INQ_PAGE86;
- }
+ rsp_buf[3] = 4;
+ rsp_buf[4] = SPC_INQ_PAGE0;
+ rsp_buf[5] = SPC_INQ_PAGE80;
+ rsp_buf[6] = SPC_INQ_PAGE83;
+ rsp_buf[7] = SPC_INQ_PAGE86;
/*
* Return the smallest amount of data between the
@@ -422,12 +417,18 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
rbp[3] = lobyte(loword(cmd->c_lu->l_targ->s_tpgt));
rbp += vd.len;
+ assert(lu->l_guid != NULL);
/* ---- VPD descriptor ---- */
vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SPC_INQUIRY_ID_TYPE_EUI;
+ vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
vd.association = SPC_INQUIRY_ASSOC_LUN;
- vd.piv = 1;
+ /*
+ * If the ASSOCIATION field contains a value other
+ * than 01b or 10b, then the PIV bit contents are
+ * reserved. SPC-4 revision 11 section 7.6.3.1.
+ */
+ vd.piv = 0;
vd.len = lu->l_guid_len;
bcopy(&vd, rbp, sizeof (vd));
rbp += sizeof (vd);
@@ -457,7 +458,7 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
/* ---- VPD descriptor ---- */
vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SPC_INQUIRY_ID_TYPE_EUI;
+ vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
vd.association = SPC_INQUIRY_ASSOC_TARG;
vd.piv = 1;
@@ -474,7 +475,7 @@ spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
/* ---- VPD descriptor ---- */
vd.code_set = SPC_INQUIRY_CODE_SET_BINARY;
- vd.id_type = SPC_INQUIRY_ID_TYPE_EUI;
+ vd.id_type = SUN_INQUIRY_ID_TYPE(lu->l_guid);
vd.proto_id = SPC_INQUIRY_PROTOCOL_ISCSI;
vd.association = SPC_INQUIRY_ASSOC_TARGPORT;
vd.piv = 1;
diff --git a/usr/src/cmd/iscsi/iscsitgtd/target.h b/usr/src/cmd/iscsi/iscsitgtd/target.h
index f52c127529..fb3f3cb256 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/target.h
+++ b/usr/src/cmd/iscsi/iscsitgtd/target.h
@@ -158,9 +158,45 @@ typedef struct eui_16 {
e_timestamp[4];
} eui_16_t;
+/*
+ * SPC-4 revision 11, section 7.6.3.6.5
+ * NAA IEEE Registered Extended designator format
+ */
+typedef struct naa_16 {
+#if defined(_BIT_FIELDS_LTOH)
+ uchar_t n_company_id_hi : 4,
+ n_naa : 4;
+#elif defined(_BIT_FIELDS_HTOL)
+ uchar_t n_naa : 4,
+ n_company_id_hi : 4;
+#else
+#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
+#endif
+ uchar_t n_company_id_b1,
+ n_company_id_b2;
+#if defined(_BIT_FIELDS_LTOH)
+ uchar_t n_resv1 : 4,
+ n_company_id_lo : 4;
+#elif defined(_BIT_FIELDS_HTOL)
+ uchar_t n_company_id_lo : 4,
+ n_resv1 : 4;
+#else
+#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
+#endif
+ uchar_t n_timestamp[4];
+ uchar_t n_resv2;
+ uchar_t n_mac[6];
+ uchar_t n_resv3;
+} naa_16_t;
+
#define SUN_EUI_16_VERS 1
+#define SUN_NAA_16_TYPE 6
+
+#define SUN_INQUIRY_ID_TYPE(GUID) \
+ (((naa_16_t *)(GUID))->n_naa == SUN_NAA_16_TYPE ? \
+ SPC_INQUIRY_ID_TYPE_NAA : SPC_INQUIRY_ID_TYPE_EUI)
-#define SUN_EN 0x2a;
+#define SUN_EN 0x144f
#define MIN_VAL 4
#ifndef min
diff --git a/usr/src/cmd/iscsi/iscsitgtd/util.c b/usr/src/cmd/iscsi/iscsitgtd/util.c
index 0346f4bef9..2e83ec8113 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/util.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/util.c
@@ -49,6 +49,7 @@
#include "isns_client.h"
#include <sys/scsi/generic/commands.h>
#include "mgmt_scf.h"
+#include "t10_spc.h"
#define CRC32_STR "CRC32C"
#define NONE_STR "None"
@@ -58,6 +59,7 @@ static thick_provo_t *thick_head,
pthread_mutex_t thick_mutex;
static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name);
+static Boolean_t util_create_guid_naa(char **guid);
void
util_init()
@@ -1077,8 +1079,24 @@ sna_lte(uint32_t n1, uint32_t n2)
((n1 > n2) && ((n1 - n2) > SNA32_CHECK))));
}
+/*
+ * util_create_guid -- generate GUID based on the guid type
+ * id_type: SPC_INQUIRY_ID_TYPE_EUI -
+ * EUI-64 based 16-byte designator format;
+ * SPC_INQUIRY_ID_TYPE_NAA -
+ * NAA IEEE Registered Extended designator format.
+ *
+ * SPC-4 revision 11 section 7.6.3.5.4 and 7.6.3.6.5.
+ *
+ * Note that now this function is always called with parameter
+ * id_type SPC_INQUIRY_ID_TYPE_NAA, therefore the code for creating
+ * EUI-64 based 16-byte format GUID is no longer used. But in order
+ * to keep backward compatiability and for future extension, all the
+ * code that has been used for creating old GUIDs should be kept, to
+ * make the format clear for all possible GUIDs targets might have.
+ */
Boolean_t
-util_create_guid(char **guid)
+util_create_guid(char **guid, uchar_t id_type)
{
eui_16_t eui;
/*
@@ -1090,6 +1108,13 @@ util_create_guid(char **guid)
size_t guid_size;
int i, fd;
+ /*
+ * Create the NAA (6) GUID.
+ */
+ if (id_type == SPC_INQUIRY_ID_TYPE_NAA) {
+ return (util_create_guid_naa(guid));
+ }
+
if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
/*
@@ -1112,16 +1137,17 @@ util_create_guid(char **guid)
(void) close(fd);
eui.e_vers = SUN_EUI_16_VERS;
- eui.e_company_id[0] = 0;
- eui.e_company_id[1] = 0;
- eui.e_company_id[2] = SUN_EN;
+ eui.e_company_id[0] = (SUN_EN >> 16) & 0xff;
+ eui.e_company_id[1] = (SUN_EN >> 8) & 0xff;
+ eui.e_company_id[2] = SUN_EN & 0xff;
} else {
bzero(&eui, sizeof (eui));
eui.e_vers = SUN_EUI_16_VERS;
- /* ---- [0] & [1] are zero for Sun's IEEE identifier ---- */
- eui.e_company_id[2] = SUN_EN;
+ eui.e_company_id[0] = (SUN_EN >> 16) & 0xff;
+ eui.e_company_id[1] = (SUN_EN >> 8) & 0xff;
+ eui.e_company_id[2] = SUN_EN & 0xff;
eui.e_timestamp[0] = hibyte(hiword(tval));
eui.e_timestamp[1] = lobyte(hiword(tval));
eui.e_timestamp[2] = hibyte(loword(tval));
@@ -1145,6 +1171,77 @@ util_create_guid(char **guid)
return (True);
}
+Boolean_t
+util_create_guid_naa(char **guid)
+{
+ naa_16_t naa;
+ /*
+ * We only have room for 32bits of data in the GUID. The hiword/loword
+ * macros will not work on 64bit variables. The work, but produce
+ * invalid results on Big Endian based machines.
+ */
+ uint32_t tval = (uint_t)time((time_t *)0);
+ size_t guid_size;
+ int i, fd;
+
+ if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
+
+ /*
+ * By default strict GUID generation is enforced. This can
+ * be disabled by using the correct XML tag in the configuration
+ * file.
+ */
+ if (enforce_strict_guid == True)
+ return (False);
+
+ /*
+ * There's no MAC address available and we've even tried
+ * a second time to get one. So fallback to using a random
+ * number for the MAC address.
+ */
+ if ((fd = open("/dev/random", O_RDONLY)) < 0)
+ return (False);
+ if (read(fd, &naa, sizeof (naa)) != sizeof (naa))
+ return (False);
+ (void) close(fd);
+
+ } else {
+ bzero(&naa, sizeof (naa));
+
+ /*
+ * Set vendor specific identifier and extension.
+ */
+ naa.n_timestamp[0] = hibyte(hiword(tval));
+ naa.n_timestamp[1] = lobyte(hiword(tval));
+ naa.n_timestamp[2] = hibyte(loword(tval));
+ naa.n_timestamp[3] = lobyte(loword(tval));
+ for (i = 0; i < min(mac_len, sizeof (naa.n_mac)); i++) {
+ naa.n_mac[i] = mac_addr[i];
+ }
+
+ /*
+ * To prevent duplicate GUIDs we need to sleep for one
+ * second here since part of the GUID is a time stamp with
+ * a one second resolution.
+ */
+ (void) sleep(1);
+ }
+
+ /*
+ * Set NAA (6) and IEEE Company_ID.
+ */
+ naa.n_naa = SUN_NAA_16_TYPE;
+ naa.n_company_id_hi = (SUN_EN >> 20) & 0x0f;
+ naa.n_company_id_b1 = (SUN_EN >> 12) & 0xff;
+ naa.n_company_id_b2 = (SUN_EN >> 4) & 0xff;
+ naa.n_company_id_lo = SUN_EN & 0x0f;
+ if (tgt_xml_encode((uint8_t *)&naa, sizeof (naa), guid,
+ &guid_size) == False) {
+ return (False);
+ } else
+ return (True);
+}
+
/*
* []----
* | create_geom -- based on size determine best fit for CHS
diff --git a/usr/src/cmd/iscsi/iscsitgtd/utility.h b/usr/src/cmd/iscsi/iscsitgtd/utility.h
index e4208f162b..a9d2664d5f 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/utility.h
+++ b/usr/src/cmd/iscsi/iscsitgtd/utility.h
@@ -89,7 +89,7 @@ Boolean_t check_access(tgt_node_t *targ, char *initiator_name,
Boolean_t req_chap);
tgt_node_t *find_target_node(char *targ_name);
void util_title(target_queue_t *q, int type, int num, char *title);
-Boolean_t util_create_guid(char **guid);
+Boolean_t util_create_guid(char **guid, uchar_t id_type);
Boolean_t strtoll_multiplier(char *str, uint64_t *sp);
void thick_provo_stop(char *targ, int lun);
void *thick_provo_start(void *v);
diff --git a/usr/src/lib/libiscsitgt/common/xml.c b/usr/src/lib/libiscsitgt/common/xml.c
index de90d9c197..e24385179c 100644
--- a/usr/src/lib/libiscsitgt/common/xml.c
+++ b/usr/src/lib/libiscsitgt/common/xml.c
@@ -465,6 +465,9 @@ tgt_xml_encode(uint8_t *ip, size_t ip_size, char **buf, size_t *buf_size)
bp += 2;
}
+ /* make it null terminated */
+ *bp = 0;
+
return (True);
}