[stgt] [PATCH RFC 2/2] - new iser code
Alexander Nezhinsky
alexandern at voltaire.com
Wed Jul 7 14:00:12 CEST 2010
Files in patch 1/2:
iser.h iser_ib.c
Files in patch 2/2:
issci/iser_text.c iscsi/iscsid.c iscsi/iscsid.h
iscsi/iscsi_tcp.c iscsi/conn.c iscsi/session.c
iscsi/target.c iscsi/transport.h iscsi/chap.c
list.h Makefile
Signed-off-by: Alexander Nezhinsky <alexandern at voltaire.com>
---
usr/Makefile | 2 +-
usr/iscsi/chap.c | 8 +-
usr/iscsi/conn.c | 70 +++--
usr/iscsi/iscsi_tcp.c | 68 +----
usr/iscsi/iscsid.c | 468 +++++++++++++++--------------
usr/iscsi/iscsid.h | 98 ++++---
usr/iscsi/iser_text.c | 805 +++++++++++++++++++++++++++++++++++++++++++++++++
usr/iscsi/session.c | 7 +-
usr/iscsi/target.c | 199 +------------
usr/iscsi/transport.h | 3 -
usr/list.h | 3 +
11 files changed, 1165 insertions(+), 566 deletions(-)
create mode 100644 usr/iscsi/iser_text.c
diff --git a/usr/Makefile b/usr/Makefile
index 262300d..e2a6e0b 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -19,7 +19,7 @@ TGTD_OBJS += bs_rdwr.o bs_aio.o
ifneq ($(ISCSI_RDMA),)
CFLAGS += -DISCSI_RDMA
-TGTD_OBJS += iscsi/iscsi_rdma.o
+TGTD_OBJS += iscsi/iser_ib.o iscsi/iser_text.o
LIBS += -libverbs -lrdmacm
endif
endif
diff --git a/usr/iscsi/chap.c b/usr/iscsi/chap.c
index 524bab5..f047359 100644
--- a/usr/iscsi/chap.c
+++ b/usr/iscsi/chap.c
@@ -330,7 +330,7 @@ static inline void chap_calc_digest_sha1(char chap_id, char *secret, int secret_
sha1_final(&ctx, digest);
}
-static int chap_initiator_auth_create_challenge(struct iscsi_connection *conn)
+static int chap_initiator_auth_create_challenge(struct iscsi_conn_hdr *conn)
{
char *value, *p;
char text[CHAP_CHALLENGE_MAX * 2 + 8];
@@ -383,7 +383,7 @@ static int chap_initiator_auth_create_challenge(struct iscsi_connection *conn)
return 0;
}
-static int chap_initiator_auth_check_response(struct iscsi_connection *conn)
+static int chap_initiator_auth_check_response(struct iscsi_conn_hdr *conn)
{
char *value;
uint8_t *his_digest = NULL, *our_digest = NULL;
@@ -485,7 +485,7 @@ static int chap_initiator_auth_check_response(struct iscsi_connection *conn)
return retval;
}
-static int chap_target_auth_create_response(struct iscsi_connection *conn)
+static int chap_target_auth_create_response(struct iscsi_conn_hdr *conn)
{
char chap_id, *value, *response = NULL;
uint8_t *challenge = NULL, *digest = NULL;
@@ -616,7 +616,7 @@ static int chap_target_auth_create_response(struct iscsi_connection *conn)
return retval;
}
-int cmnd_exec_auth_chap(struct iscsi_connection *conn)
+int cmnd_exec_auth_chap(struct iscsi_conn_hdr *conn)
{
int res;
diff --git a/usr/iscsi/conn.c b/usr/iscsi/conn.c
index d8601e1..5d1395f 100644
--- a/usr/iscsi/conn.c
+++ b/usr/iscsi/conn.c
@@ -23,25 +23,24 @@
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
-#include <sys/epoll.h>
#include "iscsid.h"
#include "tgtd.h"
#include "util.h"
#include "tgtadm_error.h"
-void conn_add_to_session(struct iscsi_connection *conn, struct iscsi_session *session)
+void conn_add_to_session(struct iscsi_conn_hdr *conn_h, struct iscsi_session *session)
{
- if (!list_empty(&conn->clist)) {
+ if (!list_empty(&conn_h->clist)) {
eprintf("%" PRIx64 " %u\n",
- sid64(session->isid, session->tsih), conn->cid);
+ sid64(session->isid, session->tsih), conn_h->cid);
exit(0);
}
/* release in conn_free */
session_get(session);
- conn->session = session;
- list_add(&conn->clist, &session->conn_list);
+ conn_h->session = session;
+ list_add(&conn_h->clist, &session->conn_list);
}
int conn_init(struct iscsi_connection *conn)
@@ -57,11 +56,11 @@ int conn_init(struct iscsi_connection *conn)
}
conn->rsp_buffer_size = INCOMING_BUFSIZE;
- conn->refcount = 1;
- conn->state = STATE_FREE;
- param_set_defaults(conn->session_param, session_keys);
+ conn->h.refcount = 1;
+ conn->h.state = STATE_FREE;
+ param_set_defaults(conn->h.session_param, session_keys);
- INIT_LIST_HEAD(&conn->clist);
+ INIT_LIST_HEAD(&conn->h.clist);
INIT_LIST_HEAD(&conn->tx_clist);
INIT_LIST_HEAD(&conn->task_list);
@@ -70,12 +69,12 @@ int conn_init(struct iscsi_connection *conn)
void conn_exit(struct iscsi_connection *conn)
{
- struct iscsi_session *session = conn->session;
+ struct iscsi_session *session = conn->h.session;
- list_del(&conn->clist);
+ list_del(&conn->h.clist);
free(conn->req_buffer);
free(conn->rsp_buffer);
- free(conn->initiator);
+ free(conn->h.initiator);
if (session)
session_put(session);
@@ -86,31 +85,31 @@ void conn_close(struct iscsi_connection *conn)
struct iscsi_task *task, *tmp;
int ret;
- if (conn->closed) {
- eprintf("already closed %p %u\n", conn, conn->refcount);
+ if (conn->h.closed) {
+ eprintf("already closed %p %u\n", conn, conn->h.refcount);
return;
}
- conn->closed = 1;
+ conn->h.closed = 1;
ret = conn->tp->ep_close(conn);
if (ret)
eprintf("failed to close a connection, %p %u %s\n",
- conn, conn->refcount, strerror(errno));
+ conn, conn->h.refcount, strerror(errno));
else
- eprintf("connection closed, %p %u\n", conn, conn->refcount);
+ eprintf("connection closed, %p %u\n", conn, conn->h.refcount);
/* may not have been in FFP yet */
- if (!conn->session)
+ if (!conn->h.session)
goto done;
- eprintf("sesson %p %d\n", conn->session, conn->session->refcount);
+ eprintf("sesson %p %d\n", conn->h.session, conn->h.session->refcount);
/*
* We just closed the ep so we are not going to send/recv anything.
* Just free these up since they are not going to complete.
*/
- list_for_each_entry_safe(task, tmp, &conn->session->pending_cmd_list,
+ list_for_each_entry_safe(task, tmp, &conn->h.session->pending_cmd_list,
c_list) {
if (task->conn != conn)
continue;
@@ -182,25 +181,28 @@ done:
void conn_put(struct iscsi_connection *conn)
{
- conn->refcount--;
- if (!conn->refcount)
+ conn->h.refcount--;
+ if (!conn->h.refcount)
conn->tp->ep_release(conn);
}
int conn_get(struct iscsi_connection *conn)
{
/* TODO: check state */
- conn->refcount++;
+ conn->h.refcount++;
return 0;
}
struct iscsi_connection *conn_find(struct iscsi_session *session, uint32_t cid)
{
+ struct iscsi_conn_hdr *conn_h;
struct iscsi_connection *conn;
- list_for_each_entry(conn, &session->conn_list, clist) {
- if (conn->cid == cid)
+ list_for_each_entry(conn_h, &session->conn_list, clist) {
+ if (conn_h->cid == cid) {
+ conn = container_of(conn_h, struct iscsi_connection, h);
return conn;
+ }
}
return NULL;
@@ -208,9 +210,9 @@ struct iscsi_connection *conn_find(struct iscsi_session *session, uint32_t cid)
int conn_take_fd(struct iscsi_connection *conn)
{
- dprintf("%u %u %u %" PRIx64 "\n", conn->cid, conn->stat_sn,
- conn->exp_stat_sn, sid64(conn->isid, conn->tsih));
- conn->session->conn_cnt++;
+ dprintf("%u %u %u %" PRIx64 "\n", conn->h.cid, conn->h.stat_sn,
+ conn->h.exp_stat_sn, sid64(conn->h.isid, conn->h.tsih));
+ conn->h.session->conn_cnt++;
return 0;
}
@@ -219,6 +221,7 @@ int conn_close_force(uint32_t tid, uint64_t sid, uint32_t cid)
{
struct iscsi_target* target = NULL;
struct iscsi_session *session;
+ struct iscsi_conn_hdr *conn_h;
struct iscsi_connection *conn;
int sess_found = 0;
@@ -229,12 +232,11 @@ int conn_close_force(uint32_t tid, uint64_t sid, uint32_t cid)
list_for_each_entry(session, &target->sessions_list, slist) {
if (session->tsih == sid) {
sess_found = 1;
- list_for_each_entry(conn, &session->conn_list, clist) {
- if (conn->cid == cid) {
+ list_for_each_entry(conn_h, &session->conn_list, clist) {
+ if (conn_h->cid == cid) {
eprintf("close %" PRIx64 " %u\n", sid, cid);
- conn->state = STATE_CLOSE;
- conn->tp->ep_event_modify(conn,
- EPOLLIN|EPOLLOUT|EPOLLERR);
+ conn = container_of(conn_h, struct iscsi_connection, h);
+ conn_close(conn);
return TGTADM_SUCCESS;
}
}
diff --git a/usr/iscsi/iscsi_tcp.c b/usr/iscsi/iscsi_tcp.c
index d1edd84..0e6ae5b 100644
--- a/usr/iscsi/iscsi_tcp.c
+++ b/usr/iscsi/iscsi_tcp.c
@@ -1,4 +1,4 @@
-/*
+ /*
* Software iSCSI target over TCP/IP Data-Path
*
* Copyright (C) 2006-2007 FUJITA Tomonori <tomof at acm.org>
@@ -31,7 +31,6 @@
#include <netinet/tcp.h>
#include <sys/epoll.h>
#include <sys/socket.h>
-#include <pthread.h>
#include "iscsid.h"
#include "tgtd.h"
@@ -44,7 +43,6 @@ static struct iscsi_transport iscsi_tcp;
struct iscsi_tcp_connection {
int fd;
- int pthread;
struct iscsi_connection iscsi_conn;
};
@@ -136,6 +134,10 @@ static void accept_connection(int afd, int events, void *data)
tcp_conn->fd = fd;
conn->tp = &iscsi_tcp;
+ conn->h.op.conn_show = iscsi_tcp.ep_show;
+ conn->h.op.conn_getsockname = iscsi_tcp.ep_getsockname;
+ conn->h.op.conn_getpeername = iscsi_tcp.ep_getpeername;
+
conn_read_pdu(conn);
set_non_blocking(fd);
@@ -155,32 +157,19 @@ out:
static void iscsi_tcp_event_handler(int fd, int events, void *data)
{
struct iscsi_connection *conn = (struct iscsi_connection *) data;
- struct iscsi_tcp_connection *tcp_conn = TCP_CONN(conn);
if (events & EPOLLIN)
iscsi_rx_handler(conn);
- if (conn->state == STATE_CLOSE)
+ if (conn->h.state == STATE_CLOSE)
dprintf("connection closed\n");
- if (conn->state != STATE_CLOSE && events & EPOLLOUT)
+ if (conn->h.state != STATE_CLOSE && events & EPOLLOUT)
iscsi_tx_handler(conn);
- if (conn->state == STATE_CLOSE) {
+ if (conn->h.state == STATE_CLOSE) {
dprintf("connection closed %p\n", conn);
- if (tcp_conn->pthread) {
- struct iscsi_target *target = conn->session->target;
-
- pthread_mutex_lock(&target->event_lock);
- do_tgt_event_del(target->efd, &target->events_list,
- tcp_conn->fd);
- pthread_mutex_unlock(&target->event_lock);
- /* let the main thread handle this */
- tcp_conn->pthread = 0;
- tgt_event_modify(tcp_conn->fd, EPOLLIN|EPOLLOUT|EPOLLERR);
- } else {
- conn_close(conn);
- }
+ conn_close(conn);
}
}
@@ -278,29 +267,6 @@ static int iscsi_tcp_conn_login_complete(struct iscsi_connection *conn)
return 0;
}
-static void iscsi_tcp_conn_nexus_init(struct iscsi_connection *conn)
-{
- struct iscsi_tcp_connection *tcp_conn = TCP_CONN(conn);
- struct iscsi_target *target = conn->session->target;
-
- if (iscsi_pthread_per_target()) {
- /* remove the conn from the main thread. */
- conn->tp->ep_event_modify(conn, 0);
-
- pthread_mutex_lock(&target->event_lock);
-
- do_tgt_event_add(target->efd, &target->events_list,
- tcp_conn->fd, EPOLLIN,
- iscsi_tcp_event_handler, conn);
-
- pthread_mutex_unlock(&target->event_lock);
-
- tcp_conn->pthread = 1;
- }
-
- conn->tp->ep_event_modify(conn, EPOLLIN);
-}
-
static size_t iscsi_tcp_read(struct iscsi_connection *conn, void *buf,
size_t nbytes)
{
@@ -374,18 +340,9 @@ static void iscsi_event_modify(struct iscsi_connection *conn, int events)
struct iscsi_tcp_connection *tcp_conn = TCP_CONN(conn);
int ret;
- if (tcp_conn->pthread) {
- struct iscsi_target *target = conn->session->target;
-
- pthread_mutex_lock(&target->event_lock);
- do_tgt_event_modify(target->efd, &target->events_list,
- tcp_conn->fd, events);
- pthread_mutex_unlock(&target->event_lock);
- } else {
- ret = tgt_event_modify(tcp_conn->fd, events);
- if (ret)
- eprintf("tgt_event_modify failed\n");
- }
+ ret = tgt_event_modify(tcp_conn->fd, events);
+ if (ret)
+ eprintf("tgt_event_modify failed\n");
}
static struct iscsi_task *iscsi_tcp_alloc_task(struct iscsi_connection *conn,
@@ -438,7 +395,6 @@ static struct iscsi_transport iscsi_tcp = {
.ep_init = iscsi_tcp_init,
.ep_exit = iscsi_tcp_exit,
.ep_login_complete = iscsi_tcp_conn_login_complete,
- .ep_nexus_init = iscsi_tcp_conn_nexus_init,
.alloc_task = iscsi_tcp_alloc_task,
.free_task = iscsi_tcp_free_task,
.ep_read = iscsi_tcp_read,
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index 03a465c..2507140 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -38,7 +38,6 @@
#include "util.h"
#include "driver.h"
#include "scsi.h"
-#include "tgtadm.h"
#include "crc32c.h"
#define MAX_QUEUE_CMD 128
@@ -74,13 +73,6 @@ enum {
IOSTATE_TX_END,
};
-int iscsi_rdma_enabled;
-
-int iscsi_pthread_per_target(void)
-{
- return sig_fd >= 0 && !iscsi_rdma_enabled;
-}
-
void conn_read_pdu(struct iscsi_connection *conn)
{
conn->rx_iostate = IOSTATE_RX_BHS;
@@ -104,14 +96,19 @@ static struct iscsi_key login_keys[] = {
{NULL, 0, 0, 0, NULL},
};
-char *text_key_find(struct iscsi_connection *conn, char *searchKey)
+extern char *text_key_find(struct iscsi_conn_hdr *conn_h, char *searchKey)
{
- char *data, *key, *value;
- int keylen, datasize;
+ struct iscsi_connection *conn = container_of(conn_h,struct iscsi_connection,h);
+
+ return text_key_find_in_buf(conn->req.data, conn->req.datasize, searchKey);
+}
+
+char *text_key_find_in_buf(char *data, unsigned int datasize, char *searchKey)
+{
+ char *key, *value;
+ int keylen;
keylen = strlen(searchKey);
- data = conn->req.data;
- datasize = conn->req.datasize;
while (1) {
for (key = data; datasize > 0 && *data != '='; data++, datasize--)
@@ -161,29 +158,28 @@ static char *next_key(char **data, int *datasize, char **value)
return key;
}
-void text_key_add(struct iscsi_connection *conn, char *key, char *value)
+void text_key_add(struct iscsi_conn_hdr *conn_h, char *key, char *value)
{
+ struct iscsi_connection *conn = container_of(conn_h,struct iscsi_connection,h);
int keylen = strlen(key);
int valuelen = strlen(value);
int len = keylen + valuelen + 2;
- char *buffer;
int max_len;
- if (conn->state == STATE_FULL)
- max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+ if (conn->h.state == STATE_FULL)
+ max_len = conn->h.session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
else
max_len = conn->rsp_buffer_size;
if (!conn->rsp.datasize)
conn->rsp.data = conn->rsp_buffer;
- buffer = conn->rsp_buffer;
-
if (conn->rsp.datasize + len > max_len &&
(conn->req.bhs.opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_TEXT)
goto drop;
if (conn->rsp.datasize + len > conn->rsp_buffer_size) {
+ char *buffer = conn->rsp_buffer;
buffer = realloc(buffer, conn->rsp.datasize + len);
if (buffer) {
conn->rsp_buffer = buffer;
@@ -193,22 +189,32 @@ void text_key_add(struct iscsi_connection *conn, char *key, char *value)
goto drop;
}
- buffer += conn->rsp.datasize;
- conn->rsp.datasize += len;
+ text_key_add_to_buf(conn->rsp_buffer, &conn->rsp.datasize, key, value);
+ return;
+
+drop:
+ log_warning("Dropping key (%s=%s)", key, value);
+ return;
+}
+
+void text_key_add_to_buf(char *data, unsigned int *datalen, char *key, char *value)
+{
+ int keylen = strlen(key);
+ int valuelen = strlen(value);
+ int len = keylen + valuelen + 2;
+ char *buffer = data + *datalen;
strcpy(buffer, key);
buffer += keylen;
*buffer++ = '=';
strcpy(buffer, value);
- return;
-drop:
- log_warning("Dropping key (%s=%s)", key, value);
- return;
+
+ *datalen += len;
}
static void text_key_add_reject(struct iscsi_connection *conn, char *key)
{
- text_key_add(conn, key, "Reject");
+ text_key_add(&conn->h, key, "Reject");
}
static void text_scan_security(struct iscsi_connection *conn)
@@ -230,29 +236,29 @@ static void text_scan_security(struct iscsi_connection *conn)
*nextValue++ = 0;
if (!strcmp(value, "None")) {
- if (account_available(conn->tid, AUTH_DIR_INCOMING))
+ if (account_available(conn->h.tid, AUTH_DIR_INCOMING))
continue;
- conn->auth_method = AUTH_NONE;
- text_key_add(conn, key, "None");
+ conn->h.auth_method = AUTH_NONE;
+ text_key_add(&conn->h, key, "None");
break;
} else if (!strcmp(value, "CHAP")) {
- if (!account_available(conn->tid, AUTH_DIR_INCOMING))
+ if (!account_available(conn->h.tid, AUTH_DIR_INCOMING))
continue;
- conn->auth_method = AUTH_CHAP;
- text_key_add(conn, key, "CHAP");
+ conn->h.auth_method = AUTH_CHAP;
+ text_key_add(&conn->h, key, "CHAP");
break;
}
} while ((value = nextValue));
- if (conn->auth_method == AUTH_UNKNOWN)
+ if (conn->h.auth_method == AUTH_UNKNOWN)
text_key_add_reject(conn, key);
} else
- text_key_add(conn, key, "NotUnderstood");
+ text_key_add(&conn->h, key, "NotUnderstood");
}
- if (conn->auth_method == AUTH_UNKNOWN) {
+ if (conn->h.auth_method == AUTH_UNKNOWN) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
}
}
@@ -262,19 +268,21 @@ static void login_security_done(struct iscsi_connection *conn)
struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *) &conn->rsp.bhs;
struct iscsi_session *session;
- if (!conn->tid)
+ if (!conn->h.tid)
return;
- session = session_find_name(conn->tid, conn->initiator, req->isid);
+ session = session_find_name(conn->h.tid, conn->h.initiator, req->isid);
if (session) {
if (!req->tsih) {
- struct iscsi_connection *ent, *next;
+ struct iscsi_conn_hdr *ent, *next;
+ struct iscsi_connection *c;
/* do session reinstatement */
list_for_each_entry_safe(ent, next, &session->conn_list,
clist) {
- conn_close(ent);
+ c = container_of(ent, struct iscsi_connection, h);
+ conn_close(c);
}
session = NULL;
@@ -282,21 +290,21 @@ static void login_security_done(struct iscsi_connection *conn)
/* fail the login */
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
- } else if (conn_find(session, conn->cid)) {
+ } else if (conn_find(session, conn->h.cid)) {
/* do connection reinstatement */
}
/* add a new connection to the session */
if (session)
- conn_add_to_session(conn, session);
+ conn_add_to_session(&conn->h, session);
} else {
if (req->tsih) {
/* fail the login */
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_NO_SESSION;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
/*
@@ -332,7 +340,7 @@ static void text_scan_login(struct iscsi_connection *conn)
is_rdma = 1;
if (param_str_to_val(session_keys, idx, value, &val) < 0) {
- if (conn->session_param[idx].state
+ if (conn->h.session_param[idx].state
== KEY_STATE_START) {
text_key_add_reject(conn, key);
continue;
@@ -341,55 +349,55 @@ static void text_scan_login(struct iscsi_connection *conn)
ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail =
ISCSI_LOGIN_STATUS_INIT_ERR;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
goto out;
}
}
err = param_check_val(session_keys, idx, &val);
if (idx == ISCSI_PARAM_MAX_XMIT_DLENGTH &&
- conn->session_type == SESSION_DISCOVERY)
- conn->session_param[idx].val = val;
+ conn->h.session_type == SESSION_DISCOVERY)
+ conn->h.session_param[idx].val = val;
else
err = param_set_val(session_keys,
- conn->session_param,
+ conn->h.session_param,
idx, &val);
- switch (conn->session_param[idx].state) {
+ switch (conn->h.session_param[idx].state) {
case KEY_STATE_START:
if (idx == ISCSI_PARAM_MAX_XMIT_DLENGTH)
break;
memset(buf, 0, sizeof(buf));
param_val_to_str(session_keys, idx, val, buf);
- text_key_add(conn, key, buf);
+ text_key_add(&conn->h, key, buf);
break;
case KEY_STATE_REQUEST:
- if (val != conn->session_param[idx].val) {
+ if (val != conn->h.session_param[idx].val) {
rsp->status_class =
ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail =
ISCSI_LOGIN_STATUS_INIT_ERR;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
log_warning("%s %u %u\n", key,
- val, conn->session_param[idx].val);
+ val, conn->h.session_param[idx].val);
goto out;
}
break;
case KEY_STATE_DONE:
break;
}
- conn->session_param[idx].state = KEY_STATE_DONE;
+ conn->h.session_param[idx].state = KEY_STATE_DONE;
} else
- text_key_add(conn, key, "NotUnderstood");
+ text_key_add(&conn->h, key, "NotUnderstood");
}
if (is_rdma) {
/* do not try to do digests, not supported in iser */
- conn->session_param[ISCSI_PARAM_HDRDGST_EN].val = DIGEST_NONE;
- conn->session_param[ISCSI_PARAM_DATADGST_EN].val = DIGEST_NONE;
+ conn->h.session_param[ISCSI_PARAM_HDRDGST_EN].val = DIGEST_NONE;
+ conn->h.session_param[ISCSI_PARAM_DATADGST_EN].val = DIGEST_NONE;
} else {
/* do not offer RDMA, initiator must explicitly request */
- conn->session_param[ISCSI_PARAM_RDMA_EXTENSIONS].val = 0;
+ conn->h.session_param[ISCSI_PARAM_RDMA_EXTENSIONS].val = 0;
}
out:
@@ -398,13 +406,13 @@ out:
static int text_check_param(struct iscsi_connection *conn)
{
- struct param *p = conn->session_param;
+ struct param *p = conn->h.session_param;
char buf[32];
int i, cnt;
for (i = 0, cnt = 0; session_keys[i].name; i++) {
if (p[i].state == KEY_STATE_START && p[i].val != session_keys[i].def) {
- if (conn->state == STATE_LOGIN) {
+ if (conn->h.state == STATE_LOGIN) {
if (i == ISCSI_PARAM_MAX_XMIT_DLENGTH) {
if (p[i].val > session_keys[i].def)
p[i].val = session_keys[i].def;
@@ -421,7 +429,7 @@ static int text_check_param(struct iscsi_connection *conn)
memset(buf, 0, sizeof(buf));
param_val_to_str(session_keys, i, p[i].val,
buf);
- text_key_add(conn, session_keys[i].name, buf);
+ text_key_add(&conn->h, session_keys[i].name, buf);
p[i].state = KEY_STATE_REQUEST;
}
cnt++;
@@ -438,51 +446,48 @@ static void login_start(struct iscsi_connection *conn)
char *name, *alias, *session_type, *target_name;
struct iscsi_target *target;
- conn->cid = be16_to_cpu(req->cid);
- memcpy(conn->isid, req->isid, sizeof(req->isid));
- conn->tsih = req->tsih;
+ conn->h.cid = be16_to_cpu(req->cid);
+ memcpy(conn->h.isid, req->isid, sizeof(req->isid));
+ conn->h.tsih = req->tsih;
- if (!sid64(conn->isid, conn->tsih)) {
+ if (!sid64(conn->h.isid, conn->h.tsih)) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
- name = text_key_find(conn, "InitiatorName");
+ name = text_key_find(&conn->h, "InitiatorName");
if (!name) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
- conn->initiator = strdup(name);
- alias = text_key_find(conn, "InitiatorAlias");
- session_type = text_key_find(conn, "SessionType");
- target_name = text_key_find(conn, "TargetName");
+ conn->h.initiator = strdup(name);
+ alias = text_key_find(&conn->h, "InitiatorAlias");
+ session_type = text_key_find(&conn->h, "SessionType");
+ target_name = text_key_find(&conn->h, "TargetName");
- conn->auth_method = -1;
- conn->session_type = SESSION_NORMAL;
+ conn->h.auth_method = -1;
+ conn->h.session_type = SESSION_NORMAL;
if (session_type) {
if (!strcmp(session_type, "Discovery"))
- conn->session_type = SESSION_DISCOVERY;
+ conn->h.session_type = SESSION_DISCOVERY;
else if (strcmp(session_type, "Normal")) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_NO_SESSION_TYPE;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
}
- if (conn->session_type == SESSION_DISCOVERY)
- conn->tid = GLOBAL_TID;
-
- if (conn->session_type == SESSION_NORMAL) {
+ if (conn->h.session_type == SESSION_NORMAL) {
if (!target_name) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
@@ -490,41 +495,37 @@ static void login_start(struct iscsi_connection *conn)
if (!target) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
-
- conn->tid = target->tid;
-
- if (target_redirected(target, conn)) {
- char buf[NI_MAXHOST + NI_MAXSERV + 4];
- snprintf(buf, sizeof(buf), "%s:%s", target->redirect_info.addr,
- target->redirect_info.port);
- text_key_add(conn, "TargetAddress", buf);
- rsp->status_class = ISCSI_STATUS_CLS_REDIRECT;
- rsp->status_detail = target->redirect_info.reason;
- conn->state = STATE_EXIT;
+ if (target->rdma) {
+ eprintf("Target %s is RDMA, but conn cid:%d from %s is TCP\n",
+ target_name, conn->h.cid, conn->h.initiator);
+ rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn->h.state = STATE_EXIT;
return;
}
+ conn->h.tid = target->tid;
if (tgt_get_target_state(target->tid) != SCSI_TARGET_READY) {
rsp->status_class = ISCSI_STATUS_CLS_TARGET_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_TARGET_ERROR;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
- if (ip_acl(conn->tid, conn)) {
+ if (ip_acl(conn->h.tid, &conn->h)) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
- if (isns_scn_access(conn->tid, name)) {
+ if (isns_scn_access(conn->h.tid, name)) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
@@ -533,19 +534,19 @@ static void login_start(struct iscsi_connection *conn)
/* conn->target->session_cnt--; */
/* rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; */
/* rsp->status_detail = ISCSI_STATUS_TOO_MANY_CONN; */
-/* conn->state = STATE_EXIT; */
+/* conn->h.state = STATE_EXIT; */
/* return; */
/* } */
- memcpy(conn->session_param, target->session_param,
- sizeof(conn->session_param));
+ memcpy(conn->h.session_param, target->session_param,
+ sizeof(conn->h.session_param));
}
- conn->exp_cmd_sn = be32_to_cpu(req->cmdsn);
- conn->max_cmd_sn = conn->exp_cmd_sn + 1;
- dprintf("exp_cmd_sn: %d,%d\n", conn->exp_cmd_sn, req->cmdsn);
+ conn->h.exp_cmd_sn = be32_to_cpu(req->cmdsn);
+ conn->h.max_cmd_sn = conn->h.exp_cmd_sn + 1;
+ dprintf("exp_cmd_sn: %d,%d\n", conn->h.exp_cmd_sn, req->cmdsn);
- text_key_add(conn, "TargetPortalGroupTag", "1");
+ text_key_add(&conn->h, "TargetPortalGroupTag", "1");
}
static void login_finish(struct iscsi_connection *conn)
@@ -554,7 +555,7 @@ static void login_finish(struct iscsi_connection *conn)
int ret;
uint8_t class, detail;
- switch (conn->session_type) {
+ switch (conn->h.session_type) {
case SESSION_NORMAL:
/*
* Allocate transport resources for this connection.
@@ -565,29 +566,29 @@ static void login_finish(struct iscsi_connection *conn)
detail = ISCSI_LOGIN_STATUS_NO_RESOURCES;
goto fail;
}
- if (!conn->session) {
- ret = session_create(conn);
+ if (!conn->h.session) {
+ ret = session_create(&conn->h);
if (ret) {
class = ISCSI_STATUS_CLS_TARGET_ERR;
detail = ISCSI_LOGIN_STATUS_TARGET_ERROR;
goto fail;
}
} else {
- if (conn->tp->rdma ^ conn->session->rdma) {
+ if (conn->tp->rdma ^ conn->h.session->rdma) {
eprintf("new conn rdma %d, but session %d\n",
- conn->tp->rdma, conn->session->rdma);
+ conn->tp->rdma, conn->h.session->rdma);
class = ISCSI_STATUS_CLS_INITIATOR_ERR;
detail =ISCSI_LOGIN_STATUS_INVALID_REQUEST;
goto fail;
}
}
- memcpy(conn->isid, conn->session->isid, sizeof(conn->isid));
- conn->tsih = conn->session->tsih;
+ memcpy(conn->h.isid, conn->h.session->isid, sizeof(conn->h.isid));
+ conn->h.tsih = conn->h.session->tsih;
break;
case SESSION_DISCOVERY:
/* set a dummy tsih value */
- conn->tsih = 1;
+ conn->h.tsih = 1;
break;
}
@@ -596,7 +597,7 @@ fail:
rsp->flags = 0;
rsp->status_class = class;
rsp->status_detail = detail;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
@@ -604,15 +605,17 @@ static int cmnd_exec_auth(struct iscsi_connection *conn)
{
int res;
- switch (conn->auth_method) {
+ switch (conn->h.auth_method) {
case AUTH_CHAP:
- res = cmnd_exec_auth_chap(conn);
+ res = cmnd_exec_auth_chap(&conn->h);
+ eprintf("CHAP currently unsupported\n");
+ res = -3;
break;
case AUTH_NONE:
res = 0;
break;
default:
- eprintf("Unknown auth. method %d\n", conn->auth_method);
+ eprintf("Unknown auth. method %d\n", conn->h.auth_method);
res = -3;
}
@@ -630,9 +633,9 @@ static void cmnd_reject(struct iscsi_connection *conn, uint8_t reason)
rsp->ffffffff = ISCSI_RESERVED_TAG;
rsp->flags = ISCSI_FLAG_CMD_FINAL;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.max_cmd_sn);
conn->rsp.data = conn->rsp_buffer;
conn->rsp.datasize = BHS_SIZE;
@@ -661,19 +664,19 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
req->min_version > ISCSI_DRAFT20_VERSION) {
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_NO_VERSION;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
switch (ISCSI_LOGIN_CURRENT_STAGE(req->flags)) {
case ISCSI_SECURITY_NEGOTIATION_STAGE:
dprintf("Login request (security negotiation): %d\n",
- conn->state);
+ conn->h.state);
rsp->flags = ISCSI_SECURITY_NEGOTIATION_STAGE << 2;
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_FREE:
- conn->state = STATE_SECURITY;
+ conn->h.state = STATE_SECURITY;
login_start(conn);
if (rsp->status_class)
return;
@@ -682,9 +685,9 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
text_scan_security(conn);
if (rsp->status_class)
return;
- if (conn->auth_method != AUTH_NONE) {
- conn->state = STATE_SECURITY_AUTH;
- conn->auth_state = AUTH_STATE_START;
+ if (conn->h.auth_method != AUTH_NONE) {
+ conn->h.state = STATE_SECURITY_AUTH;
+ conn->h.auth_state = AUTH_STATE_START;
}
break;
case STATE_SECURITY_AUTH:
@@ -705,15 +708,15 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
break;
case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
dprintf("Login request (operational negotiation): %d\n",
- conn->state);
+ conn->h.state);
rsp->flags = ISCSI_OP_PARMS_NEGOTIATION_STAGE << 2;
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_FREE:
- conn->state = STATE_LOGIN;
+ conn->h.state = STATE_LOGIN;
login_start(conn);
- if (account_available(conn->tid, AUTH_DIR_INCOMING))
+ if (account_available(conn->h.tid, AUTH_DIR_INCOMING))
goto auth_err;
if (rsp->status_class)
return;
@@ -738,16 +741,16 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
if (rsp->status_class)
return;
- if (conn->state != STATE_SECURITY_AUTH &&
+ if (conn->h.state != STATE_SECURITY_AUTH &&
req->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
int nsg = ISCSI_LOGIN_NEXT_STAGE(req->flags);
switch (nsg) {
case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_SECURITY:
case STATE_SECURITY_DONE:
- conn->state = STATE_SECURITY_LOGIN;
+ conn->h.state = STATE_SECURITY_LOGIN;
login_security_done(conn);
break;
default:
@@ -755,22 +758,22 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
}
break;
case ISCSI_FULL_FEATURE_PHASE:
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_SECURITY:
case STATE_SECURITY_DONE:
if ((nsg_disagree = text_check_param(conn))) {
- conn->state = STATE_LOGIN;
+ conn->h.state = STATE_LOGIN;
nsg = ISCSI_OP_PARMS_NEGOTIATION_STAGE;
break;
}
- conn->state = STATE_SECURITY_FULL;
+ conn->h.state = STATE_SECURITY_FULL;
login_security_done(conn);
break;
case STATE_LOGIN:
if (stay)
nsg = ISCSI_OP_PARMS_NEGOTIATION_STAGE;
else
- conn->state = STATE_LOGIN_FULL;
+ conn->h.state = STATE_LOGIN_FULL;
break;
default:
goto init_err;
@@ -787,23 +790,23 @@ static void cmnd_exec_login(struct iscsi_connection *conn)
rsp->flags |= nsg | (stay ? 0 : ISCSI_FLAG_LOGIN_TRANSIT);
}
- memcpy(rsp->isid, conn->isid, sizeof(rsp->isid));
- rsp->tsih = conn->tsih;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
+ memcpy(rsp->isid, conn->h.isid, sizeof(rsp->isid));
+ rsp->tsih = conn->h.tsih;
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.max_cmd_sn);
return;
init_err:
rsp->flags = 0;
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_INIT_ERR;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
auth_err:
rsp->flags = 0;
rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
rsp->status_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED;
- conn->state = STATE_EXIT;
+ conn->h.state = STATE_EXIT;
return;
}
@@ -815,6 +818,7 @@ static void text_scan_text(struct iscsi_connection *conn)
data = conn->req.data;
datasize = conn->req.datasize;
+ dprintf("entry\n");
while ((key = next_key(&data, &datasize, &value))) {
if (!strcmp(key, "SendTargets")) {
struct sockaddr_storage ss;
@@ -829,7 +833,8 @@ static void text_scan_text(struct iscsi_connection *conn)
blen = sizeof(buf);
slen = sizeof(ss);
- ret = conn->tp->ep_getsockname(conn,
+
+ ret = conn->h.op.conn_getsockname(&conn->h,
(struct sockaddr *)&ss,
&slen);
if (ret) {
@@ -858,27 +863,31 @@ static void text_scan_text(struct iscsi_connection *conn)
target_list_build(conn, buf,
strcmp(value, "All") ? value : NULL);
} else
- text_key_add(conn, key, "NotUnderstood");
+ text_key_add(&conn->h, key, "NotUnderstood");
}
+ dprintf("exit\n");
}
static void cmnd_exec_text(struct iscsi_connection *conn)
{
struct iscsi_text *req = (struct iscsi_text *)&conn->req.bhs;
struct iscsi_text_rsp *rsp = (struct iscsi_text_rsp *)&conn->rsp.bhs;
- int max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+ int max_len = conn->h.session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
memset(rsp, 0, BHS_SIZE);
rsp->opcode = ISCSI_OP_TEXT_RSP;
rsp->itt = req->itt;
- conn->exp_cmd_sn = be32_to_cpu(req->cmdsn);
+ /* rsp->ttt = rsp->ttt; */
+ rsp->ttt = 0xffffffff;
+ conn->h.exp_cmd_sn = be32_to_cpu(req->cmdsn);
if (!(req->opcode & ISCSI_OP_IMMEDIATE))
- conn->exp_cmd_sn++;
+ conn->h.exp_cmd_sn++;
if (be32_to_cpu(req->ttt) == ISCSI_RESERVED_TAG) {
conn->text_datasize = 0;
+ dprintf("Text request: %d\n", conn->h.state);
text_scan_text(conn);
conn->text_rsp_buffer = conn->rsp_buffer;
@@ -907,9 +916,9 @@ static void cmnd_exec_text(struct iscsi_connection *conn)
rsp->ttt = cpu_to_be32(conn->ttt);
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.max_cmd_sn);
}
static void cmnd_exec_logout(struct iscsi_connection *conn)
@@ -921,13 +930,13 @@ static void cmnd_exec_logout(struct iscsi_connection *conn)
rsp->opcode = ISCSI_OP_LOGOUT_RSP;
rsp->flags = ISCSI_FLAG_CMD_FINAL;
rsp->itt = req->itt;
- conn->exp_cmd_sn = be32_to_cpu(req->cmdsn);
+ conn->h.exp_cmd_sn = be32_to_cpu(req->cmdsn);
if (!(req->opcode & ISCSI_OP_IMMEDIATE))
- conn->exp_cmd_sn++;
+ conn->h.exp_cmd_sn++;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.max_cmd_sn);
}
static int cmnd_execute(struct iscsi_connection *conn)
@@ -961,20 +970,20 @@ static int cmnd_execute(struct iscsi_connection *conn)
static void cmnd_finish(struct iscsi_connection *conn)
{
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_EXIT:
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
break;
case STATE_SECURITY_LOGIN:
- conn->state = STATE_LOGIN;
+ conn->h.state = STATE_LOGIN;
break;
case STATE_SECURITY_FULL:
/* fall through */
case STATE_LOGIN_FULL:
- if (conn->session_type == SESSION_NORMAL)
- conn->state = STATE_KERNEL;
+ if (conn->h.session_type == SESSION_NORMAL)
+ conn->h.state = STATE_KERNEL;
else
- conn->state = STATE_FULL;
+ conn->h.state = STATE_FULL;
break;
}
}
@@ -1027,9 +1036,9 @@ static int iscsi_cmd_rsp_build(struct iscsi_task *task)
rsp->flags = ISCSI_FLAG_CMD_FINAL;
rsp->response = ISCSI_STATUS_CMD_COMPLETED;
rsp->cmd_status = scsi_get_result(&task->scmd);
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn + MAX_QUEUE_CMD);
calc_residual(rsp, task);
@@ -1067,8 +1076,8 @@ static int iscsi_data_rsp_build(struct iscsi_task *task)
datalen -= task->offset;
maxdatalen = conn->tp->rdma ?
- conn->session_param[ISCSI_PARAM_MAX_BURST].val :
- conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+ conn->h.session_param[ISCSI_PARAM_MAX_BURST].val :
+ conn->h.session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
dprintf("%d %d %d %" PRIu32 "%x\n", datalen,
scsi_get_in_length(&task->scmd), task->len, maxdatalen,
@@ -1083,14 +1092,14 @@ static int iscsi_data_rsp_build(struct iscsi_task *task)
!conn->tp->rdma) {
rsp->flags |= ISCSI_FLAG_DATA_STATUS;
rsp->cmd_status = result;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
calc_residual((struct iscsi_cmd_rsp *) rsp, task);
}
} else
datalen = maxdatalen;
- rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn + MAX_QUEUE_CMD);
conn->rsp.datasize = datalen;
hton24(rsp->dlength, datalen);
@@ -1118,10 +1127,10 @@ static int iscsi_r2t_build(struct iscsi_task *task)
rsp->r2tsn = cpu_to_be32(task->exp_r2tsn++);
rsp->data_offset = cpu_to_be32(task->offset);
/* return next statsn for this conn w/o advancing it */
- rsp->statsn = cpu_to_be32(conn->stat_sn);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn);
rsp->ttt = (unsigned long) task;
length = min_t(uint32_t, task->r2t_count,
- conn->session_param[ISCSI_PARAM_MAX_BURST].val);
+ conn->h.session_param[ISCSI_PARAM_MAX_BURST].val);
rsp->data_length = cpu_to_be32(length);
return 0;
@@ -1193,7 +1202,7 @@ static int iscsi_scsi_cmd_done(uint64_t nid, int result, struct scsi_cmd *scmd)
* the response with a little extra code or we can check if this
* task got reassinged to another connection.
*/
- if (task->conn->state == STATE_CLOSE) {
+ if (task->conn->h.state == STATE_CLOSE) {
iscsi_free_cmd_task(task);
return 0;
}
@@ -1248,7 +1257,7 @@ static int iscsi_target_cmd_queue(struct iscsi_task *task)
int err;
enum data_direction dir = scsi_get_data_dir(scmd);
- scmd->cmd_itn_id = conn->session->tsih;
+ scmd->cmd_itn_id = conn->h.session->tsih;
scmd->scb = req->cdb;
scmd->scb_len = sizeof(req->cdb);
@@ -1322,7 +1331,7 @@ static int iscsi_target_cmd_queue(struct iscsi_task *task)
scmd->tag = req->itt;
set_task_in_scsi(task);
- err = target_cmd_queue(conn->session->target->tid, scmd);
+ err = target_cmd_queue(conn->h.session->target->tid, scmd);
if (err)
clear_task_in_scsi(task);
@@ -1415,8 +1424,8 @@ static int iscsi_tm_execute(struct iscsi_task *task)
task->result = err;
else {
int ret;
- ret = target_mgmt_request(conn->session->target->tid,
- conn->session->tsih,
+ ret = target_mgmt_request(conn->h.session->target->tid,
+ conn->h.session->tsih,
(unsigned long)task, fn, req->lun,
req->itt, 0);
set_task_in_scsi(task);
@@ -1503,7 +1512,7 @@ static int iscsi_data_out_rx_start(struct iscsi_connection *conn)
struct iscsi_task *task;
struct iscsi_data *req = (struct iscsi_data *) &conn->req.bhs;
- list_for_each_entry(task, &conn->session->cmd_list, c_hlist) {
+ list_for_each_entry(task, &conn->h.session->cmd_list, c_hlist) {
if (task->tag == req->itt)
goto found;
}
@@ -1527,7 +1536,7 @@ found:
static int iscsi_task_queue(struct iscsi_task *task)
{
- struct iscsi_session *session = task->conn->session;
+ struct iscsi_session *session = task->conn->h.session;
struct iscsi_hdr *req = (struct iscsi_hdr *) &task->req;
uint32_t cmd_sn;
struct iscsi_task *ent;
@@ -1587,7 +1596,7 @@ static int iscsi_scsi_cmd_rx_start(struct iscsi_connection *conn)
imm_len = roundup(ntoh24(req->dlength), conn->tp->data_padding);
data_len = roundup(ntohl(req->data_length), conn->tp->data_padding);
- dprintf("%u %x %d %d %d %x %x\n", conn->session->tsih,
+ dprintf("%u %x %d %d %d %x %x\n", conn->h.session->tsih,
req->cdb[0], ahs_len, imm_len, data_len,
req->flags & ISCSI_FLAG_CMD_ATTR_MASK, req->itt);
@@ -1617,7 +1626,7 @@ static int iscsi_scsi_cmd_rx_start(struct iscsi_connection *conn)
task->unsol_count, task->offset);
}
- list_add(&task->c_hlist, &conn->session->cmd_list);
+ list_add(&task->c_hlist, &conn->h.session->cmd_list);
return 0;
}
@@ -1646,7 +1655,7 @@ static int iscsi_noop_out_rx_start(struct iscsi_connection *conn)
}
}
- conn->exp_stat_sn = be32_to_cpu(req->exp_statsn);
+ conn->h.exp_stat_sn = be32_to_cpu(req->exp_statsn);
len = ntoh24(req->dlength);
task = iscsi_alloc_task(conn, 0, len);
@@ -1706,12 +1715,12 @@ static int iscsi_task_rx_start(struct iscsi_connection *conn)
case ISCSI_OP_SCSI_CMD:
err = iscsi_scsi_cmd_rx_start(conn);
if (!err)
- conn->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
+ conn->h.exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
break;
case ISCSI_OP_SCSI_DATA_OUT:
err = iscsi_data_out_rx_start(conn);
if (!err)
- conn->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
+ conn->h.exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
break;
case ISCSI_OP_NOOP_OUT:
err = iscsi_noop_out_rx_start(conn);
@@ -1761,9 +1770,9 @@ static int iscsi_logout_tx_start(struct iscsi_task *task)
rsp->opcode = ISCSI_OP_LOGOUT_RSP;
rsp->flags = ISCSI_FLAG_CMD_FINAL;
rsp->itt = task->req.itt;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn + MAX_QUEUE_CMD);
return 0;
}
@@ -1784,9 +1793,9 @@ static int iscsi_noop_out_tx_start(struct iscsi_task *task, int *is_rsp)
rsp->flags = ISCSI_FLAG_CMD_FINAL;
rsp->itt = task->req.itt;
rsp->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn + MAX_QUEUE_CMD);
/* TODO: honor max_burst */
conn->rsp.datasize = task->len;
@@ -1808,9 +1817,9 @@ static int iscsi_tm_tx_start(struct iscsi_task *task)
rsp->itt = task->req.itt;
rsp->response = task->result;
- rsp->statsn = cpu_to_be32(conn->stat_sn++);
- rsp->exp_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn);
- rsp->max_cmdsn = cpu_to_be32(conn->session->exp_cmd_sn + MAX_QUEUE_CMD);
+ rsp->statsn = cpu_to_be32(conn->h.stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn->h.session->exp_cmd_sn + MAX_QUEUE_CMD);
return 0;
}
@@ -1859,7 +1868,7 @@ static int iscsi_task_tx_done(struct iscsi_connection *conn)
iscsi_free_task(task);
if (op == ISCSI_OP_LOGOUT)
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
}
conn->tx_task = NULL;
@@ -1916,7 +1925,7 @@ static int do_recv(struct iscsi_connection *conn, int next_state)
ret = conn->tp->ep_read(conn, conn->rx_buffer, conn->rx_size);
if (!ret) {
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
return 0;
} else if (ret < 0) {
if (errno == EINTR || errno == EAGAIN)
@@ -1938,8 +1947,8 @@ void iscsi_rx_handler(struct iscsi_connection *conn)
int ret = 0, hdigest, ddigest;
uint32_t crc;
- if (conn->state == STATE_SCSI) {
- struct param *p = conn->session_param;
+ if (conn->h.state == STATE_SCSI) {
+ struct param *p = conn->h.session_param;
hdigest = p[ISCSI_PARAM_HDRDGST_EN].val & DIGEST_CRC32C;
ddigest = p[ISCSI_PARAM_DATADGST_EN].val & DIGEST_CRC32C;
} else
@@ -1951,10 +1960,10 @@ again:
if (ret <= 0 || conn->rx_iostate != IOSTATE_RX_INIT_AHS)
break;
case IOSTATE_RX_INIT_AHS:
- if (conn->state == STATE_SCSI) {
+ if (conn->h.state == STATE_SCSI) {
ret = iscsi_task_rx_start(conn);
if (ret) {
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
break;
}
} else {
@@ -2009,7 +2018,7 @@ again:
if (*((uint32_t *)conn->rx_digest) != crc) {
eprintf("rx hdr digest error 0x%x calc 0x%x\n",
*((uint32_t *)conn->rx_digest), crc);
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
}
conn->rx_iostate = IOSTATE_RX_INIT_DATA;
case IOSTATE_RX_INIT_DATA:
@@ -2045,29 +2054,29 @@ again:
if (*((uint32_t *)conn->rx_digest) != crc) {
eprintf("rx hdr digest error 0x%x calc 0x%x\n",
*((uint32_t *)conn->rx_digest), crc);
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
}
break;
default:
- eprintf("error %d %d\n", conn->state, conn->rx_iostate);
+ eprintf("error %d %d\n", conn->h.state, conn->rx_iostate);
exit(1);
}
if (ret < 0 ||
conn->rx_iostate != IOSTATE_RX_END ||
- conn->state == STATE_CLOSE)
+ conn->h.state == STATE_CLOSE)
return;
if (conn->rx_size) {
- eprintf("error %d %d %d\n", conn->state, conn->rx_iostate,
+ eprintf("error %d %d %d\n", conn->h.state, conn->rx_iostate,
conn->rx_size);
exit(1);
}
- if (conn->state == STATE_SCSI) {
+ if (conn->h.state == STATE_SCSI) {
ret = iscsi_task_rx_done(conn);
if (ret)
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
else
conn_read_pdu(conn);
} else {
@@ -2075,7 +2084,7 @@ again:
conn->tp->ep_event_modify(conn, EPOLLOUT);
ret = cmnd_execute(conn);
if (ret)
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
}
}
@@ -2086,7 +2095,7 @@ again:
ret = conn->tp->ep_write_begin(conn, conn->tx_buffer, conn->tx_size);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
else if (errno == EINTR || errno == EAGAIN)
goto again;
@@ -2107,14 +2116,14 @@ int iscsi_tx_handler(struct iscsi_connection *conn)
int ret = 0, hdigest, ddigest;
uint32_t crc;
- if (conn->state == STATE_SCSI) {
- struct param *p = conn->session_param;
+ if (conn->h.state == STATE_SCSI) {
+ struct param *p = conn->h.session_param;
hdigest = p[ISCSI_PARAM_HDRDGST_EN].val & DIGEST_CRC32C;
ddigest = p[ISCSI_PARAM_DATADGST_EN].val & DIGEST_CRC32C;
} else
hdigest = ddigest = 0;
- if (conn->state == STATE_SCSI && !conn->tx_task) {
+ if (conn->h.state == STATE_SCSI && !conn->tx_task) {
ret = iscsi_task_tx_start(conn);
if (ret)
goto out;
@@ -2124,7 +2133,7 @@ int iscsi_tx_handler(struct iscsi_connection *conn)
* For rdma, grab the data-in or r2t packet and covert to
* an RDMA operation.
*/
- if (conn->tp->rdma && conn->state == STATE_SCSI) {
+ if (conn->tp->rdma && conn->h.state == STATE_SCSI) {
switch (conn->rsp.bhs.opcode) {
case ISCSI_OP_R2T:
ret = conn->tp->ep_rdma_read(conn);
@@ -2215,11 +2224,11 @@ again:
ret = do_send(conn, IOSTATE_TX_END);
break;
default:
- eprintf("error %d %d\n", conn->state, conn->tx_iostate);
+ eprintf("error %d %d\n", conn->h.state, conn->tx_iostate);
exit(1);
}
- if (ret < 0 || conn->state == STATE_CLOSE)
+ if (ret < 0 || conn->h.state == STATE_CLOSE)
goto out;
if (conn->tx_iostate != IOSTATE_TX_END) {
@@ -2229,7 +2238,7 @@ again:
}
if (conn->tx_size) {
- eprintf("error %d %d %d\n", conn->state, conn->tx_iostate,
+ eprintf("error %d %d %d\n", conn->h.state, conn->tx_iostate,
conn->tx_size);
exit(1);
}
@@ -2239,15 +2248,15 @@ again:
finish:
cmnd_finish(conn);
- switch (conn->state) {
+ switch (conn->h.state) {
case STATE_KERNEL:
ret = conn_take_fd(conn);
if (ret)
- conn->state = STATE_CLOSE;
+ conn->h.state = STATE_CLOSE;
else {
- conn->state = STATE_SCSI;
+ conn->h.state = STATE_SCSI;
conn_read_pdu(conn);
- conn->tp->ep_nexus_init(conn);
+ conn->tp->ep_event_modify(conn, EPOLLIN);
}
break;
case STATE_EXIT:
@@ -2266,7 +2275,7 @@ out:
return ret;
}
-static int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size)
+int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size)
{
struct iscsi_session *session;
char *p;
@@ -2340,14 +2349,11 @@ static int iscsi_param_parser(char *p)
else
len = strlen(addr);
- if (iscsi_portal_addr) {
- free(iscsi_portal_addr);
- iscsi_portal_addr = NULL;
- }
- if (len) {
- iscsi_portal_addr = zalloc(len + 1);
- memcpy(iscsi_portal_addr, addr, len);
- }
+ iscsi_portal_addr = zalloc(len + 1);
+ memcpy(iscsi_portal_addr, addr, len);
+
+ eprintf("Listen port:%d Portal addr:%s\n",
+ iscsi_listen_port, iscsi_portal_addr);
}
p += strcspn(p, ",");
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index 7e501a4..d6dd064 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -21,7 +21,6 @@
#include <stdint.h>
#include <inttypes.h>
-#include <netdb.h>
#include "transport.h"
#include "list.h"
@@ -132,16 +131,33 @@ struct iscsi_task {
unsigned long extdata[0];
};
-struct iscsi_connection {
- int state;
+struct iscsi_conn_hdr;
+struct iscsi_conn_ops {
+
+ int (*conn_show)(struct iscsi_conn_hdr *conn, char *buf, int rest);
+ int (*conn_getsockname)(struct iscsi_conn_hdr *conn,
+ struct sockaddr *sa, socklen_t *len);
+ int (*conn_getpeername)(struct iscsi_conn_hdr *conn,
+ struct sockaddr *sa, socklen_t *len);
+};
+
+struct iscsi_conn_hdr {
+ int state;
/* should be a new state */
int closed;
- int rx_iostate;
- int tx_iostate;
int refcount;
+ struct iscsi_conn_ops op;
+
+ uint32_t stat_sn;
+ uint32_t exp_stat_sn;
+
+ uint32_t cmd_sn;
+ uint32_t exp_cmd_sn;
+ uint32_t max_cmd_sn;
+
struct list_head clist;
struct iscsi_session *session;
@@ -155,12 +171,22 @@ struct iscsi_connection {
int session_type;
int auth_method;
- uint32_t stat_sn;
- uint32_t exp_stat_sn;
+ int auth_state;
+ union {
+ struct {
+ int digest_alg;
+ int id;
+ int challenge_size;
+ unsigned char *challenge;
+ } chap;
+ } auth;
+};
- uint32_t cmd_sn;
- uint32_t exp_cmd_sn;
- uint32_t max_cmd_sn;
+struct iscsi_connection {
+ struct iscsi_conn_hdr h;
+
+ int rx_iostate;
+ int tx_iostate;
struct iscsi_pdu req;
void *req_buffer;
@@ -186,16 +212,6 @@ struct iscsi_connection {
unsigned char rx_digest[4];
unsigned char tx_digest[4];
- int auth_state;
- union {
- struct {
- int digest_alg;
- int id;
- int challenge_size;
- unsigned char *challenge;
- } chap;
- } auth;
-
struct iscsi_transport *tp;
};
@@ -212,6 +228,9 @@ struct iscsi_connection {
#define STATE_CLOSE 10
#define STATE_EXIT 11
#define STATE_SCSI 12
+#define STATE_INIT 13
+#define STATE_START 14
+#define STATE_READY 15
#define AUTH_STATE_START 0
#define AUTH_STATE_CHALLENGE 1
@@ -244,20 +263,9 @@ struct iscsi_target {
int max_nr_sessions;
int nr_sessions;
- struct redirect_info {
- char addr[NI_MAXHOST + 1];
- char port[NI_MAXSERV + 1];
- uint8_t reason;
- } redirect_info;
-
struct list_head isns_list;
- int efd;
- pthread_mutex_t event_lock;
- struct list_head events_list;
-
- struct bs_finish bsfin;
- int stop_pthread;
+ int rdma;
};
enum task_flags {
@@ -280,7 +288,7 @@ extern int lld_index;
extern struct list_head iscsi_targets_list;
/* chap.c */
-extern int cmnd_exec_auth_chap(struct iscsi_connection *conn);
+extern int cmnd_exec_auth_chap(struct iscsi_conn_hdr *conn_h);
/* conn.c */
extern int conn_init(struct iscsi_connection *conn);
@@ -290,12 +298,14 @@ extern void conn_put(struct iscsi_connection *conn);
extern int conn_get(struct iscsi_connection *conn);
extern struct iscsi_connection * conn_find(struct iscsi_session *session, uint32_t cid);
extern int conn_take_fd(struct iscsi_connection *conn);
-extern void conn_add_to_session(struct iscsi_connection *conn, struct iscsi_session *session);
+extern void conn_add_to_session(struct iscsi_conn_hdr *conn, struct iscsi_session *session);
extern int conn_close_force(uint32_t tid, uint64_t sid, uint32_t cid);
/* iscsid.c */
-extern char *text_key_find(struct iscsi_connection *conn, char *searchKey);
-extern void text_key_add(struct iscsi_connection *conn, char *key, char *value);
+extern char *text_key_find_in_buf(char *data,unsigned int datasize, char *searchKey);
+extern void text_key_add_to_buf(char *data, unsigned int *datalen, char *key, char *value);
+extern char *text_key_find(struct iscsi_conn_hdr *conn, char *searchKey);
+extern void text_key_add(struct iscsi_conn_hdr *conn, char *key, char *value);
extern void conn_read_pdu(struct iscsi_connection *conn);
extern int iscsi_tx_handler(struct iscsi_connection *conn);
extern void iscsi_rx_handler(struct iscsi_connection *conn);
@@ -308,24 +318,22 @@ extern void iscsi_free_cmd_task(struct iscsi_task *task);
/* session.c */
extern struct iscsi_session *session_find_name(int tid, const char *iname, uint8_t *isid);
extern struct iscsi_session *session_lookup_by_tsih(uint16_t tsih);
-extern int session_create(struct iscsi_connection *conn);
+extern int session_create(struct iscsi_conn_hdr *conn);
extern void session_get(struct iscsi_session *session);
extern void session_put(struct iscsi_session *session);
/* target.c */
-struct iscsi_target * target_find_by_name(const char *name);
-struct iscsi_target * target_find_by_id(int tid);
+extern struct iscsi_target * target_find_by_name(const char *name);
+extern struct iscsi_target * target_find_by_id(int tid);
extern void target_list_build(struct iscsi_connection *, char *, char *);
-extern int ip_acl(int tid, struct iscsi_connection *conn);
+extern int ip_acl(int tid, struct iscsi_conn_hdr *conn);
extern int iscsi_target_create(struct target *);
extern void iscsi_target_destroy(int);
extern int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid,
uint64_t lun, char *buf, int rest);
-int iscsi_target_update(int mode, int op, int tid, uint64_t sid, uint64_t lun,
- uint32_t cid, char *name);
-int target_redirected(struct iscsi_target *target, struct iscsi_connection *conn);
-
-int iscsi_pthread_per_target(void);
+extern int iscsi_target_update(int mode, int op, int tid, uint64_t sid, uint64_t lun,
+ uint32_t cid, char *name);
+extern int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size);
/* param.c */
int param_index_by_name(char *name, struct iscsi_key *keys);
diff --git a/usr/iscsi/iser_text.c b/usr/iscsi/iser_text.c
new file mode 100644
index 0000000..ce0cecf
--- /dev/null
+++ b/usr/iscsi/iser_text.c
@@ -0,0 +1,805 @@
+/*
+ * iSCSI extensions for RDMA (iSER)
+ * LOGIN and TEXT related code
+ *
+ * Copyright (C) 2007 Dennis Dalessandro (dennis at osc.edu)
+ * Copyright (C) 2007 Ananth Devulapalli (ananth at osc.edu)
+ * Copyright (C) 2007 Pete Wyckoff (pw at osc.edu)
+ * Copyright (c) 2010 Voltaire, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <netdb.h>
+#include <sys/epoll.h>
+#include <infiniband/verbs.h>
+#include <rdma/rdma_cma.h>
+
+#include "util.h"
+#include "iscsid.h"
+#include "iser.h"
+
+#if defined(HAVE_VALGRIND) && !defined(NDEBUG)
+ #include <valgrind/memcheck.h>
+#else
+ #define VALGRIND_MAKE_MEM_DEFINED(addr, len)
+#endif
+
+
+static struct iscsi_key login_keys[] = {
+ {"InitiatorName",},
+ {"InitiatorAlias",},
+ {"SessionType",},
+ {"TargetName",},
+ {NULL, 0, 0, 0, NULL},
+};
+
+static char *iser_text_next_key(char **data, int *datasize, char **value)
+{
+ char *key, *p, *q;
+ int size = *datasize;
+
+ key = p = *data;
+ for (; size > 0 && *p != '='; p++, size--)
+ ;
+ if (!size)
+ return NULL;
+ *p++ = 0;
+ size--;
+
+ for (q = p; size > 0 && *p != 0; p++, size--)
+ ;
+ if (!size)
+ return NULL;
+ p++;
+ size--;
+
+ *data = p;
+ *value = q;
+ *datasize = size;
+
+ return key;
+}
+
+char *iser_text_key_find(char *data, int datasize, char *searchKey)
+{
+ int keylen = strlen(searchKey);
+ char *key, *value;
+
+ while (1) {
+ for (key = data; datasize > 0 && *data != '='; data++, datasize--)
+ ;
+ if (!datasize)
+ return NULL;
+ data++;
+ datasize--;
+
+ for (value = data; datasize > 0 && *data != 0; data++, datasize--)
+ ;
+ if (!datasize)
+ return NULL;
+ data++;
+ datasize--;
+
+ if (keylen == value - key - 1
+ && !strncmp(key, searchKey, keylen))
+ return value;
+ }
+}
+
+void iser_text_key_add(struct iser_task *task, char *key, char *value)
+{
+ struct iser_conn *conn = task->conn;
+ int keylen = strlen(key);
+ int valuelen = strlen(value);
+ int len = keylen + valuelen + 2;
+ char *buffer = task->rsp.data.buf;
+
+ if (task->rsp.data.size + len > conn->ssize) {
+ log_warning("Dropping key (%s=%s)", key, value);
+ return;
+ }
+
+ buffer += task->rsp.data.size;
+ task->rsp.data.size += len;
+
+ strcpy(buffer, key);
+ buffer += keylen;
+ *buffer++ = '=';
+ strcpy(buffer, value);
+}
+
+static void iser_text_key_add_reject(struct iser_task *task, char *key)
+{
+ iser_text_key_add(task, key, "Reject");
+}
+
+static void iser_login_security_scan(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)task->rsp.bhs;
+ char *key, *value, *data, *nextValue;
+ int datasize;
+
+ data = task->req.data.buf;
+ datasize = task->req.data.size;
+
+ while ((key = iser_text_next_key(&data, &datasize, &value))) {
+ if (!(param_index_by_name(key, login_keys) < 0))
+ ;
+ else if (!strcmp(key, "AuthMethod")) {
+ do {
+ nextValue = strchr(value, ',');
+ if (nextValue)
+ *nextValue++ = 0;
+
+ if (!strcmp(value, "None")) {
+ if (account_available(conn_h->tid, AUTH_DIR_INCOMING))
+ continue;
+ conn_h->auth_method = AUTH_NONE;
+ iser_text_key_add(task, key, "None");
+ break;
+ } else if (!strcmp(value, "CHAP")) {
+ if (!account_available(conn_h->tid, AUTH_DIR_INCOMING))
+ continue;
+ conn_h->auth_method = AUTH_CHAP;
+ iser_text_key_add(task, key, "CHAP");
+ break;
+ }
+ } while ((value = nextValue));
+
+ if (conn_h->auth_method == AUTH_UNKNOWN)
+ iser_text_key_add_reject(task, key);
+ } else
+ iser_text_key_add(task, key, "NotUnderstood");
+ }
+ if (conn_h->auth_method == AUTH_UNKNOWN) {
+ rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED;
+ conn_h->state = STATE_EXIT;
+ }
+}
+
+static void iser_login_security_done(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)task->rsp.bhs;
+ struct iscsi_login *req = (struct iscsi_login *)task->req.bhs;
+ struct iscsi_session *session;
+
+ if (!conn_h->tid)
+ return;
+
+ session = session_find_name(conn_h->tid, conn_h->initiator, req->isid);
+ if (session) {
+ if (!req->tsih) {
+ struct iscsi_conn_hdr *ent, *next;
+ struct iser_conn *c;
+
+ /* do session reinstatement */
+
+ list_for_each_entry_safe(ent, next, &session->conn_list,
+ clist) {
+ c = container_of(ent, struct iser_conn, h);
+ iser_conn_close(c);
+ }
+
+ session = NULL;
+ } else if (req->tsih != session->tsih) {
+ /* fail the login */
+ rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn_h->state = STATE_EXIT;
+ return;
+ } else if (conn_find(session, conn_h->cid)) {
+ /* do connection reinstatement */
+ }
+
+ /* add a new connection to the session */
+ if (session)
+ conn_add_to_session(conn_h, session);
+ } else {
+ if (req->tsih) {
+ /* fail the login */
+ rsp->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail = ISCSI_LOGIN_STATUS_NO_SESSION;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+ /*
+ * We do nothing here and instantiate a new session
+ * later at login_finish().
+ */
+ }
+}
+
+static void iser_login_oper_scan(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login_rsp *rsp = (struct iscsi_login_rsp *)task->rsp.bhs;
+ char *key, *value, *data;
+ int datasize, idx, is_rdma = 0;
+
+ data = task->req.data.buf;
+ datasize = task->req.data.size;
+
+ while ((key = iser_text_next_key(&data, &datasize, &value))) {
+ if (!(param_index_by_name(key, login_keys) < 0))
+ ;
+ else if (!strcmp(key, "AuthMethod"))
+ ;
+ else if (!((idx = param_index_by_name(key, session_keys)) < 0)) {
+ int err;
+ unsigned int val;
+ char buf[32];
+
+ if (idx == ISCSI_PARAM_MAX_RECV_DLENGTH)
+ idx = ISCSI_PARAM_MAX_XMIT_DLENGTH;
+
+ if (idx == ISCSI_PARAM_RDMA_EXTENSIONS)
+ is_rdma = 1;
+
+ if (param_str_to_val(session_keys, idx, value, &val) < 0) {
+ if (conn_h->session_param[idx].state
+ == KEY_STATE_START) {
+ iser_text_key_add_reject(task, key);
+ continue;
+ } else {
+ rsp->status_class =
+ ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail =
+ ISCSI_LOGIN_STATUS_INIT_ERR;
+ conn_h->state = STATE_EXIT;
+ goto out;
+ }
+ }
+
+ err = param_check_val(session_keys, idx, &val);
+ err = param_set_val(session_keys, conn_h->session_param, idx, &val);
+
+ switch (conn_h->session_param[idx].state) {
+ case KEY_STATE_START:
+ if (idx == ISCSI_PARAM_MAX_XMIT_DLENGTH)
+ break;
+ memset(buf, 0, sizeof(buf));
+ param_val_to_str(session_keys, idx, val, buf);
+ iser_text_key_add(task, key, buf);
+ break;
+ case KEY_STATE_REQUEST:
+ if (val != conn_h->session_param[idx].val) {
+ rsp->status_class =
+ ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp->status_detail =
+ ISCSI_LOGIN_STATUS_INIT_ERR;
+ conn_h->state = STATE_EXIT;
+ log_warning("%s %u %u\n", key,
+ val, conn_h->session_param[idx].val);
+ goto out;
+ }
+ break;
+ case KEY_STATE_DONE:
+ break;
+ }
+ conn_h->session_param[idx].state = KEY_STATE_DONE;
+ } else
+ iser_text_key_add(task, key, "NotUnderstood");
+ }
+
+ if (is_rdma) {
+ /* do not try to do digests, not supported in iser */
+ conn_h->session_param[ISCSI_PARAM_HDRDGST_EN].val = DIGEST_NONE;
+ conn_h->session_param[ISCSI_PARAM_DATADGST_EN].val = DIGEST_NONE;
+ } else {
+ /* do not offer RDMA, initiator must explicitly request */
+ conn_h->session_param[ISCSI_PARAM_RDMA_EXTENSIONS].val = 0;
+ }
+
+out:
+ return;
+}
+
+static int iser_login_check_params(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct param *p = conn_h->session_param;
+ char buf[32];
+ int i, cnt;
+
+ for (i = 0, cnt = 0; session_keys[i].name; i++) {
+ if (p[i].state == KEY_STATE_START && p[i].val != session_keys[i].def) {
+ if (conn_h->state == STATE_LOGIN) {
+ if (i == ISCSI_PARAM_MAX_XMIT_DLENGTH) {
+ if (p[i].val > session_keys[i].def)
+ p[i].val = session_keys[i].def;
+ p[i].state = KEY_STATE_DONE;
+ continue;
+ }
+ if (p[ISCSI_PARAM_RDMA_EXTENSIONS].val == 1) {
+ if (i == ISCSI_PARAM_MAX_RECV_DLENGTH)
+ continue;
+ } else {
+ if (i >= ISCSI_PARAM_RDMA_EXTENSIONS)
+ continue;
+ }
+ memset(buf, 0, sizeof(buf));
+ param_val_to_str(session_keys, i, p[i].val,
+ buf);
+ iser_text_key_add(task, session_keys[i].name, buf);
+ p[i].state = KEY_STATE_REQUEST;
+ }
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+static int iser_login_auth_exec(struct iscsi_conn_hdr *conn_h)
+{
+ int res;
+
+ switch (conn_h->auth_method) {
+ case AUTH_CHAP:
+ res = cmnd_exec_auth_chap(conn_h);
+ eprintf("CHAP currently unsupported\n");
+ res = -3;
+ break;
+ case AUTH_NONE:
+ res = 0;
+ break;
+ default:
+ eprintf("Unknown auth. method %d\n", conn_h->auth_method);
+ res = -3;
+ }
+
+ return res;
+}
+
+static void iser_login_start(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login *req_bhs = (struct iscsi_login *)task->req.bhs;
+ struct iscsi_login_rsp *rsp_bhs = (struct iscsi_login_rsp *)task->rsp.bhs;
+ char *req_data = task->req.data.buf;
+ int req_datasize = task->req.data.size;
+ char *name, *alias, *session_type, *target_name;
+ struct iscsi_target *target;
+
+ conn_h->cid = be16_to_cpu(req_bhs->cid);
+ memcpy(conn_h->isid, req_bhs->isid, sizeof(req_bhs->isid));
+ conn_h->tsih = req_bhs->tsih;
+
+ if (!sid64(conn_h->isid, conn_h->tsih)) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+ name = iser_text_key_find(req_data, req_datasize, "InitiatorName");
+ if (!name) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+ conn_h->initiator = strdup(name);
+ alias = iser_text_key_find(req_data, req_datasize, "InitiatorAlias");
+ session_type = iser_text_key_find(req_data, req_datasize, "SessionType");
+ target_name = iser_text_key_find(req_data, req_datasize, "TargetName");
+
+ conn_h->auth_method = -1;
+ conn_h->session_type = SESSION_NORMAL;
+
+ if (session_type) {
+ if (!strcmp(session_type, "Discovery"))
+ conn_h->session_type = SESSION_DISCOVERY;
+ else if (strcmp(session_type, "Normal")) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_NO_SESSION_TYPE;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+ }
+
+ if (conn_h->session_type == SESSION_NORMAL) {
+ if (!target_name) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+ target = target_find_by_name(target_name);
+ if (!target) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+ if (!target->rdma) {
+ eprintf("Target %s is TCP, but conn cid:%d from %s is RDMA\n",
+ target_name, conn_h->cid, conn_h->initiator);
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+ conn_h->tid = target->tid;
+
+ if (tgt_get_target_state(target->tid) != SCSI_TARGET_READY) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_TARGET_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_TARGET_ERROR;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+ if (ip_acl(conn_h->tid, conn_h)) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+ if (isns_scn_access(conn_h->tid, name)) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_TGT_NOT_FOUND;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+/* if (conn_h->target->max_sessions && */
+/* (++conn_h->target->session_cnt > conn_h->target->max_sessions)) { */
+/* conn_h->target->session_cnt--; */
+/* rsp_bhs->status_class = ISCSI_STATUS_INITIATOR_ERR; */
+/* rsp_bhs->status_detail = ISCSI_STATUS_TOO_MANY_CONN; */
+/* conn_h->state = STATE_EXIT; */
+/* return; */
+/* } */
+
+ memcpy(conn_h->session_param, target->session_param,
+ sizeof(conn_h->session_param));
+ conn_h->exp_cmd_sn = be32_to_cpu(req_bhs->cmdsn);
+ dprintf("exp_cmd_sn: %d,%d\n", conn_h->exp_cmd_sn, req_bhs->cmdsn);
+ conn_h->max_cmd_sn = conn_h->exp_cmd_sn;
+ }
+ iser_text_key_add(task, "TargetPortalGroupTag", "1");
+}
+
+static void iser_login_finish(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login_rsp *rsp_bhs = (struct iscsi_login_rsp *)task->rsp.bhs;
+ int err;
+ uint8_t class, detail;
+
+ switch (conn_h->session_type) {
+ case SESSION_NORMAL:
+ /*
+ * update based on negotiations (but ep_login_complete
+ * could override)
+ */
+ //conn_h->data_inout_max_length =
+ //conn_h->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
+
+ /*
+ * Allocate transport resources for this connection.
+ */
+ err = iser_login_complete(conn_h);
+ if (err) {
+ class = ISCSI_STATUS_CLS_TARGET_ERR;
+ detail = ISCSI_LOGIN_STATUS_NO_RESOURCES;
+ goto fail;
+ }
+ if (!conn_h->session) {
+ err = session_create(conn_h);
+ if (err) {
+ class = ISCSI_STATUS_CLS_TARGET_ERR;
+ detail = ISCSI_LOGIN_STATUS_TARGET_ERROR;
+ goto fail;
+ }
+ } else {
+ /*
+ if (conn_h->rdma ^ conn_h->session->rdma) {
+ eprintf("new conn_h rdma %d, but session %d\n",
+ conn_h->rdma, conn_h->session->rdma);
+
+ class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ detail =ISCSI_LOGIN_STATUS_INVALID_REQUEST;
+ goto fail;
+ }
+ */
+ }
+ memcpy(conn_h->isid, conn_h->session->isid, sizeof(conn_h->isid));
+ conn_h->tsih = conn_h->session->tsih;
+ break;
+ case SESSION_DISCOVERY:
+ /* set a dummy tsih value */
+ conn_h->tsih = 1;
+ break;
+ }
+
+ return;
+fail:
+ rsp_bhs->flags = 0;
+ rsp_bhs->status_class = class;
+ rsp_bhs->status_detail = detail;
+ conn_h->state = STATE_EXIT;
+ return;
+}
+
+void iser_login_exec(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_login *req_bhs = (struct iscsi_login *)task->req.bhs;
+ struct iscsi_login_rsp *rsp_bhs = (struct iscsi_login_rsp *)task->rsp.bhs;
+ int stay = 0, nsg_disagree = 0;
+
+ memset(rsp_bhs, 0, BHS_SIZE);
+ if ((req_bhs->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_LOGIN ||
+ !(req_bhs->opcode & ISCSI_OP_IMMEDIATE)) {
+ /* reject */
+ }
+
+ rsp_bhs->opcode = ISCSI_OP_LOGIN_RSP;
+ rsp_bhs->max_version = ISCSI_DRAFT20_VERSION;
+ rsp_bhs->active_version = ISCSI_DRAFT20_VERSION;
+ rsp_bhs->itt = req_bhs->itt;
+
+ if (/* req_bhs->max_version < ISCSI_VERSION || */
+ req_bhs->min_version > ISCSI_DRAFT20_VERSION) {
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_NO_VERSION;
+ conn_h->state = STATE_EXIT;
+ return;
+ }
+
+ conn_h->exp_cmd_sn = conn_h->max_cmd_sn = ntohl(req_bhs->cmdsn);
+
+ switch (ISCSI_LOGIN_CURRENT_STAGE(req_bhs->flags)) {
+ case ISCSI_SECURITY_NEGOTIATION_STAGE:
+ dprintf("Login request (security negotiation): %d\n",
+ conn_h->state);
+ rsp_bhs->flags = ISCSI_SECURITY_NEGOTIATION_STAGE << 2;
+
+ switch (conn_h->state) {
+ case STATE_READY:
+ conn_h->state = STATE_SECURITY;
+ iser_login_start(task);
+
+ if (rsp_bhs->status_class)
+ return;
+ /* fall through */
+ case STATE_SECURITY:
+ iser_login_security_scan(task);
+ if (rsp_bhs->status_class)
+ return;
+ if (conn_h->auth_method != AUTH_NONE) {
+ conn_h->state = STATE_SECURITY_AUTH;
+ conn_h->auth_state = AUTH_STATE_START;
+ }
+ break;
+ case STATE_SECURITY_AUTH:
+ switch (iser_login_auth_exec(conn_h)) {
+ case 0:
+ break;
+ default:
+ case -1:
+ goto init_err;
+ case -2:
+ goto auth_err;
+ }
+ break;
+ default:
+ goto init_err;
+ }
+
+ break;
+ case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
+ dprintf("Login request (operational negotiation): %d\n",
+ conn_h->state);
+ rsp_bhs->flags = ISCSI_OP_PARMS_NEGOTIATION_STAGE << 2;
+
+ switch (conn_h->state) {
+ case STATE_READY:
+ conn_h->state = STATE_LOGIN;
+ iser_login_start(task);
+
+ if (account_available(conn_h->tid, AUTH_DIR_INCOMING))
+ goto auth_err;
+ if (rsp_bhs->status_class)
+ return;
+ iser_login_oper_scan(task);
+ if (rsp_bhs->status_class)
+ return;
+ stay = iser_login_check_params(task);
+ break;
+ case STATE_LOGIN:
+ iser_login_oper_scan(task);
+ if (rsp_bhs->status_class)
+ return;
+ stay = iser_login_check_params(task);
+ break;
+ default:
+ goto init_err;
+ }
+ break;
+ default:
+ goto init_err;
+ }
+
+ if (rsp_bhs->status_class)
+ return;
+ if (conn_h->state != STATE_SECURITY_AUTH &&
+ req_bhs->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
+ int nsg = ISCSI_LOGIN_NEXT_STAGE(req_bhs->flags);
+
+ switch (nsg) {
+ case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
+ switch (conn_h->state) {
+ case STATE_SECURITY:
+ case STATE_SECURITY_DONE:
+ conn_h->state = STATE_SECURITY_LOGIN;
+ iser_login_security_done(task);
+ break;
+ default:
+ goto init_err;
+ }
+ break;
+ case ISCSI_FULL_FEATURE_PHASE:
+ switch (conn_h->state) {
+ case STATE_SECURITY:
+ case STATE_SECURITY_DONE:
+ if ((nsg_disagree = iser_login_check_params(task))) {
+ conn_h->state = STATE_LOGIN;
+ nsg = ISCSI_OP_PARMS_NEGOTIATION_STAGE;
+ break;
+ }
+ conn_h->state = STATE_SECURITY_FULL;
+ iser_login_security_done(task);
+ break;
+ case STATE_LOGIN:
+ if (stay)
+ nsg = ISCSI_OP_PARMS_NEGOTIATION_STAGE;
+ else
+ conn_h->state = STATE_LOGIN_FULL;
+ break;
+ default:
+ goto init_err;
+ }
+ if (!stay && !nsg_disagree) {
+ iser_login_finish(task);
+
+ if (rsp_bhs->status_class)
+ return;
+ }
+ break;
+ default:
+ goto init_err;
+ }
+ rsp_bhs->flags |= nsg | (stay ? 0 : ISCSI_FLAG_LOGIN_TRANSIT);
+ }
+
+ if (conn_h->exp_cmd_sn == ntohl(req_bhs->cmdsn))
+ conn_h->exp_cmd_sn ++;
+
+ memcpy(rsp_bhs->isid, conn_h->isid, sizeof(rsp_bhs->isid));
+ rsp_bhs->tsih = conn_h->tsih;
+ rsp_bhs->statsn = cpu_to_be32(conn_h->stat_sn++);
+ rsp_bhs->exp_cmdsn = cpu_to_be32(conn_h->exp_cmd_sn);
+ rsp_bhs->max_cmdsn = cpu_to_be32(conn_h->max_cmd_sn);
+ return;
+
+init_err:
+ rsp_bhs->flags = 0;
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_INIT_ERR;
+ conn_h->state = STATE_EXIT;
+ return;
+
+auth_err:
+ rsp_bhs->flags = 0;
+ rsp_bhs->status_class = ISCSI_STATUS_CLS_INITIATOR_ERR;
+ rsp_bhs->status_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED;
+ conn_h->state = STATE_EXIT;
+ return;
+}
+
+static void iser_text_scan(struct iser_task *task)
+{
+/*
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ char *key, *value, *data;
+ int datasize;
+
+ data = task->req.data.buf;
+ datasize = task->req.data.size;
+
+ while ((key = iser_text_next_key(&data, &datasize, &value))) {
+ if (!strcmp(key, "SendTargets")) {
+ struct sockaddr_storage ss;
+ socklen_t slen, blen;
+ char *p, buf[NI_MAXHOST + 128];
+
+ if (value[0] == 0)
+ continue;
+
+ p = buf;
+ blen = sizeof(buf);
+
+ slen = sizeof(ss);
+ conn_h->op.conn_getsockname(conn_h, (struct sockaddr *) &ss,
+ &slen);
+ if (ss.ss_family == AF_INET6) {
+ *p++ = '[';
+ blen--;
+ }
+
+ slen = sizeof(ss);
+ getnameinfo((struct sockaddr *) &ss, slen, p, blen,
+ NULL, 0, NI_NUMERICHOST);
+
+ p = buf + strlen(buf);
+
+ if (ss.ss_family == AF_INET6)
+ *p++ = ']';
+
+ sprintf(p, ":%d,1", ISCSI_LISTEN_PORT);
+ target_list_build(conn_h, buf,
+ strcmp(value, "All") ? value : NULL);
+ } else
+ iser_text_key_add(task, key, "NotUnderstood");
+ }
+*/
+}
+
+int iser_text_exec(struct iser_task *task)
+{
+ struct iscsi_conn_hdr *conn_h = &task->conn->h;
+ struct iscsi_text *req = (struct iscsi_text *)task->rsp.bhs;
+ struct iscsi_text_rsp *rsp = (struct iscsi_text_rsp *)task->req.bhs;
+
+ memset(rsp, 0, BHS_SIZE);
+
+ if (be32_to_cpu(req->ttt) != 0xffffffff) {
+ /* reject */;
+ }
+ rsp->opcode = ISCSI_OP_TEXT_RSP;
+ rsp->itt = req->itt;
+ /* rsp->ttt = rsp->ttt; */
+ rsp->ttt = 0xffffffff;
+ conn_h->exp_cmd_sn = be32_to_cpu(req->cmdsn);
+ if (!(req->opcode & ISCSI_OP_IMMEDIATE))
+ conn_h->exp_cmd_sn++;
+
+ dprintf("Text request: %d\n", conn_h->state);
+ iser_text_scan(task);
+
+ if (req->flags & ISCSI_FLAG_CMD_FINAL)
+ rsp->flags = ISCSI_FLAG_CMD_FINAL;
+
+ rsp->statsn = cpu_to_be32(conn_h->stat_sn++);
+ rsp->exp_cmdsn = cpu_to_be32(conn_h->exp_cmd_sn);
+ rsp->max_cmdsn = cpu_to_be32(conn_h->max_cmd_sn);
+
+ return 0;
+}
+
diff --git a/usr/iscsi/session.c b/usr/iscsi/session.c
index 46864c7..1872264 100644
--- a/usr/iscsi/session.c
+++ b/usr/iscsi/session.c
@@ -62,7 +62,7 @@ struct iscsi_session *session_lookup_by_tsih(uint16_t tsih)
return NULL;
}
-int session_create(struct iscsi_connection *conn)
+int session_create(struct iscsi_conn_hdr *conn)
{
int err;
struct iscsi_session *session = NULL;
@@ -70,7 +70,6 @@ int session_create(struct iscsi_connection *conn)
struct iscsi_target *target;
char addr[128];
-
target = target_find_by_id(conn->tid);
if (!target)
return -EINVAL;
@@ -103,7 +102,7 @@ int session_create(struct iscsi_connection *conn)
}
memset(addr, 0, sizeof(addr));
- conn->tp->ep_show(conn, addr, sizeof(addr));
+ conn->op.conn_show(conn, addr, sizeof(addr));
snprintf(session->info, 1024, _TAB3 "Initiator: %s\n"
_TAB3 "Connection: %u\n"
@@ -128,8 +127,6 @@ int session_create(struct iscsi_connection *conn)
memcpy(session->isid, conn->isid, sizeof(session->isid));
session->tsih = last_tsih = tsih;
- session->rdma = conn->tp->rdma;
-
conn_add_to_session(conn, session);
dprintf("session_create: %#" PRIx64 "\n", sid64(conn->isid, session->tsih));
diff --git a/usr/iscsi/target.c b/usr/iscsi/target.c
index fe44b9f..d96030f 100644
--- a/usr/iscsi/target.c
+++ b/usr/iscsi/target.c
@@ -25,7 +25,6 @@
#include <unistd.h>
#include <netdb.h>
#include <sys/stat.h>
-#include <sys/epoll.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/socket.h>
@@ -33,12 +32,10 @@
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
-#include <pthread.h>
#include "iscsid.h"
#include "tgtadm.h"
#include "tgtd.h"
#include "target.h"
-#include "util.h"
LIST_HEAD(iscsi_targets_list);
@@ -117,7 +114,7 @@ static int address_match(struct sockaddr *sa1, struct sockaddr *sa2)
return 0;
}
-static int ip_match(struct iscsi_connection *conn, char *address)
+static int ip_match(struct iscsi_conn_hdr *conn, char *address)
{
struct sockaddr_storage from;
struct addrinfo hints, *res;
@@ -126,7 +123,7 @@ static int ip_match(struct iscsi_connection *conn, char *address)
int err;
len = sizeof(from);
- err = conn->tp->ep_getpeername(conn, (struct sockaddr *) &from, &len);
+ err = conn->op.conn_getpeername(conn, (struct sockaddr *) &from, &len);
if (err < 0)
return -EPERM;
@@ -175,7 +172,7 @@ out:
return err;
}
-int ip_acl(int tid, struct iscsi_connection *conn)
+int ip_acl(int tid, struct iscsi_conn_hdr *conn)
{
int idx, err;
char *addr;
@@ -192,57 +189,6 @@ int ip_acl(int tid, struct iscsi_connection *conn)
return -EPERM;
}
-int target_redirected(struct iscsi_target *target, struct iscsi_connection *conn)
-{
- struct sockaddr_storage from;
- struct addrinfo hints, *res;
- socklen_t len;
- int ret;
- char *p, *q, *str;
-
- if (!strlen(target->redirect_info.addr))
- return 0;
-
- if (target->redirect_info.reason != ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP &&
- target->redirect_info.reason != ISCSI_LOGIN_STATUS_TGT_MOVED_PERM)
- return 0;
-
- len = sizeof(from);
- ret = conn->tp->ep_getpeername(conn, (struct sockaddr *)&from, &len);
- if (ret < 0)
- return 0;
-
- p = strdup(target->redirect_info.addr);
- if (!p)
- return 0;
- str = p;
-
- if (*p == '[') {
- p++;
- if (!(q = strchr(p, ']'))) {
- free(str);
- return 0;
- }
- *(q++) = '\0';
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_NUMERICHOST;
-
- ret = getaddrinfo(p, NULL, &hints, &res);
- if (ret < 0) {
- free(str);
- return 0;
- }
-
- ret = address_match(res->ai_addr, (struct sockaddr *)&from);
- freeaddrinfo(res);
- free(str);
-
- return !ret;
-}
-
void target_list_build(struct iscsi_connection *conn, char *addr, char *name)
{
struct iscsi_target *target;
@@ -251,14 +197,16 @@ void target_list_build(struct iscsi_connection *conn, char *addr, char *name)
if (name && strcmp(tgt_targetname(target->tid), name))
continue;
- if (ip_acl(target->tid, conn))
+ if (ip_acl(target->tid, &conn->h))
continue;
- if (isns_scn_access(target->tid, conn->initiator))
+ if (isns_scn_access(target->tid, conn->h.initiator))
continue;
- text_key_add(conn, "TargetName", tgt_targetname(target->tid));
- text_key_add(conn, "TargetAddress", addr);
+ text_key_add(&conn->h, "TargetName", tgt_targetname(target->tid));
+ text_key_add(&conn->h, "TargetAddress", addr);
+ dprintf("added TargetName:%s TargetAddress:%s rdma:%d\n",
+ tgt_targetname(target->tid), addr, target->rdma);
}
}
@@ -306,63 +254,12 @@ void iscsi_target_destroy(int tid)
}
list_del(&target->tlist);
-
- pthread_mutex_init(&target->event_lock, NULL);
-
- if (target->bsfin.thread) {
- target->stop_pthread = 1;
- pthread_kill(target->bsfin.thread, SIGUSR2);
-
- pthread_join(target->bsfin.thread, NULL);
- pthread_mutex_destroy(&target->bsfin.finished_lock);
- }
-
- close(target->efd);
free(target);
isns_target_deregister(tgt_targetname(tid));
return;
}
-static void *iscsi_thread_fn(void *arg)
-{
- struct iscsi_target *t = arg;
- struct epoll_event events[1024];
- struct event_data *tev;
- sigset_t mask;
- int nevent, i;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGUSR2);
- pthread_sigmask(SIG_BLOCK, &mask, NULL);
-
- pthread_mutex_lock(&t->event_lock);
-
- do_tgt_event_add(t->efd, &t->events_list, sig_fd, EPOLLIN,
- bs_sig_request_done, &t->bsfin);
-
- pthread_mutex_unlock(&t->event_lock);
-
-retry:
- nevent = epoll_wait(t->efd, events, ARRAY_SIZE(events), 1000);
- if (nevent < 0) {
- if (errno != EINTR) {
- eprintf("%m\n");
- exit(1);
- }
- } else if (nevent) {
- for (i = 0; i < nevent; i++) {
- tev = (struct event_data *) events[i].data.ptr;
- tev->handler(tev->fd, events[i].events, tev->data);
- }
- }
-
- if (!t->stop_pthread)
- goto retry;
-
- pthread_exit(NULL);
-}
-
int iscsi_target_create(struct target *t)
{
int tid = t->tid;
@@ -393,15 +290,11 @@ int iscsi_target_create(struct target *t)
[ISCSI_PARAM_MAX_OUTST_PDU] = {0, 0}, /* not in open-iscsi */
};
- target = zalloc(sizeof(*target));
+ target = malloc(sizeof(*target));
if (!target)
return -ENOMEM;
- target->efd = epoll_create(128);
- if (target->efd < 0) {
- free(target);
- return -EINVAL;
- }
+ memset(target, 0, sizeof(*target));
memcpy(target->session_param, default_tgt_session_param,
sizeof(target->session_param));
@@ -409,21 +302,10 @@ int iscsi_target_create(struct target *t)
INIT_LIST_HEAD(&target->tlist);
INIT_LIST_HEAD(&target->sessions_list);
INIT_LIST_HEAD(&target->isns_list);
- INIT_LIST_HEAD(&target->events_list);
target->tid = tid;
list_add_tail(&target->tlist, &iscsi_targets_list);
isns_target_register(tgt_targetname(tid));
-
- if (iscsi_pthread_per_target()) {
- pthread_create(&target->bsfin.thread, NULL, iscsi_thread_fn, target);
-
- pthread_mutex_init(&target->bsfin.finished_lock, NULL);
- INIT_LIST_HEAD(&target->bsfin.finished_list);
- t->bsf = &target->bsfin;
- eprintf("create thread %u\n", (unsigned)target->bsfin.thread);
- }
-
return 0;
}
@@ -467,29 +349,6 @@ int iscsi_target_update(int mode, int op, int tid, uint64_t sid, uint64_t lun,
dprintf("%s:%s\n", name, str);
- if (!strncmp(name, "RedirectAddress", 15)) {
- snprintf(target->redirect_info.addr,
- sizeof(target->redirect_info.addr), "%s", str);
- err = TGTADM_SUCCESS;
- break;
- } else if (!strncmp(name, "RedirectPort", 12)) {
- snprintf(target->redirect_info.port,
- sizeof(target->redirect_info.port), "%s", str);
- err = TGTADM_SUCCESS;
- break;
- } else if (!strncmp(name, "RedirectReason", 14)) {
- if (!strncmp(str, "Temporary", 9)) {
- target->redirect_info.reason =
- ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP;
- err = TGTADM_SUCCESS;
- } else if (!strncmp(str, "Permanent", 9)) {
- target->redirect_info.reason =
- ISCSI_LOGIN_STATUS_TGT_MOVED_PERM;
- err = TGTADM_SUCCESS;
- } else
- break;
- }
-
idx = param_index_by_name(name, session_keys);
if (idx >= 0) {
err = iscsi_session_param_update(target, idx, str);
@@ -537,37 +396,6 @@ static int iscsi_target_show_session(struct iscsi_target* target, uint64_t sid,
return total;
}
-#define __buffer_check(buf, total, len, rest) \
-({ \
- buf += len; \
- total += len; \
- rest -= len; \
- if (!rest) \
- return total; \
-})
-
-static int show_redirect_info(struct iscsi_target* target, char *buf, int rest)
-{
- int len, total = 0;
-
- len = snprintf(buf, rest, "RedirectAddress=%s\n", target->redirect_info.addr);
- __buffer_check(buf, total, len, rest);
- len = snprintf(buf, rest, "RedirectPort=%s\n", target->redirect_info.port);
- __buffer_check(buf, total, len, rest);
- if (target->redirect_info.reason == ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP) {
- len = snprintf(buf, rest, "RedirectReason=Temporary\n");
- __buffer_check(buf, total, len, rest);
- } else if (target->redirect_info.reason == ISCSI_LOGIN_STATUS_TGT_MOVED_PERM) {
- len = snprintf(buf, rest, "RedirectReason=Permanent\n");
- __buffer_check(buf, total, len, rest);
- } else {
- len = snprintf(buf, rest, "RedirectReason=Unknown\n");
- __buffer_check(buf, total, len, rest);
- }
-
- return total;
-}
-
int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lun,
char *buf, int rest)
{
@@ -585,10 +413,7 @@ int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lu
total = isns_show(buf, rest);
break;
case MODE_TARGET:
- if (strlen(target->redirect_info.addr))
- len = show_redirect_info(target, buf, rest);
- else
- len = show_iscsi_param(buf, target->session_param, rest);
+ len = show_iscsi_param(buf, target->session_param, rest);
total += len;
break;
case MODE_SESSION:
diff --git a/usr/iscsi/transport.h b/usr/iscsi/transport.h
index c94b86b..92a6f0a 100644
--- a/usr/iscsi/transport.h
+++ b/usr/iscsi/transport.h
@@ -4,8 +4,6 @@
#include <sys/socket.h>
#include "list.h"
-extern int iscsi_rdma_enabled;
-
struct iscsi_connection;
struct iscsi_task;
@@ -19,7 +17,6 @@ struct iscsi_transport {
int (*ep_init) (void);
void (*ep_exit) (void);
int (*ep_login_complete)(struct iscsi_connection *conn);
- void (*ep_nexus_init)(struct iscsi_connection *conn);
struct iscsi_task *(*alloc_task)(struct iscsi_connection *conn,
size_t ext_len);
void (*free_task)(struct iscsi_task *task);
diff --git a/usr/list.h b/usr/list.h
index f66ff36..2f80a56 100644
--- a/usr/list.h
+++ b/usr/list.h
@@ -43,6 +43,9 @@ static inline int list_empty(const struct list_head *head)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
--
1.6.5
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list