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 |