/*
 *  Copyright (C) 2002 - 2003 Ardis Technologies <roman@ardistech.com>
 *  Copyright (C) 2007 - 2018 Vladislav Bolkhovitin
 *  Copyright (C) 2007 - 2018 Western Digital Corporation
 *
 *  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.
 */

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "iscsid.h"

int iscsi_enabled;

static u32 ttt;

static u32 get_next_ttt(struct connection *conn __attribute__((unused)))
{
	ttt += 1;
	return (ttt == ISCSI_RESERVED_TAG) ? ++ttt : ttt;
}

static struct iscsi_key login_keys[] = {
	{ .name = "InitiatorName",},
	{ .name = "InitiatorAlias",},
	{ .name = "SessionType",},
	{ .name = "TargetName",},
	{ .name = "InitiatorRecvDataSegmentLength",},
	{ .name = "MaxAHSLength",},
	{ .name = "TaggedBufferForSolicitedDataOnly",},
	{ .name = "iSERHelloRequired",},
	{ .name = NULL,},
};

char *text_key_find(struct connection *conn, const char *searchKey)
{
	char *data, *key, *value;
	int keylen, datasize;

	keylen = strlen(searchKey);
	data = conn->req.data;
	datasize = conn->req.datasize;

	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
		     && !strncasecmp(key, searchKey, keylen))
			return value;
	}
}

static char *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;
}

static struct buf_segment *conn_alloc_buf_segment(struct connection *conn,
						   size_t sz)
{
	struct buf_segment *seg = malloc(sizeof(*seg) + sz);

	if (seg) {
		seg->len = 0;
		memset(seg->data, 0x0, sz);
		list_add_tail(&seg->entry, &conn->rsp_buf_list);
		log_debug(2, "alloc'ed new buf_segment");
	}

	return seg;
}

void text_key_add(struct connection *conn, const char *key, const char *value)
{
	struct buf_segment *seg;
	int keylen = strlen(key);
	int valuelen = strlen(value);
	int len = keylen + valuelen + 2;
	int off = 0;
	int sz = 0;
	int stage = 0;
	size_t data_sz;

	data_sz = (conn->state == STATE_FULL) ?
		conn->session_params[key_max_xmit_data_length].val :
		INCOMING_BUFSIZE;

	seg = list_empty(&conn->rsp_buf_list) ? NULL :
		list_entry(conn->rsp_buf_list.q_back, struct buf_segment,
			   entry);

	while (len) {
		if (!seg || seg->len == data_sz) {
			seg = conn_alloc_buf_segment(conn, data_sz);
			if (!seg) {
				log_error("Failed to alloc text buf segment\n");
				conn_free_rsp_buf_list(conn);
				break;
			}
		}
		switch (stage) {
		case 0:
			sz = min_t(int, data_sz - seg->len, keylen - off);
			strncpy(seg->data + seg->len, key + off, sz);
			if (sz == data_sz - seg->len) {
				off += sz;
				if (keylen - off == 0) {
					off = 0;
					stage++;
				}
			} else {
				off = 0;
				stage++;
			}
			break;
		case 1:
			seg->data[seg->len] = '=';
			off = 0;
			sz = 1;
			stage++;
			break;
		case 2:
			sz = min_t(int, data_sz - seg->len, valuelen - off);
			strncpy(seg->data + seg->len, value + off, sz);
			off += sz;
			if (valuelen - off == 0) {
				off = 0;
				stage++;
			}
			break;
		case 3:
			seg->data[seg->len] = 0;
			sz = 1;
			break;
		}

		log_debug(2, "wrote: %s", seg->data + seg->len);

		seg->len += sz;
		len -= sz;
	}
}

static void text_key_add_reject(struct connection *conn, char *key)
{
	text_key_add(conn, key, "Reject");
}

static void login_rsp_ini_err(struct connection *conn, int status_detail)
{
	struct iscsi_login_rsp_hdr * const rsp =
		(struct iscsi_login_rsp_hdr * const)&conn->rsp.bhs;

	rsp->status_class = ISCSI_STATUS_INITIATOR_ERR;
	rsp->status_detail = status_detail;
	conn->state = STATE_EXIT;
	return;
}

static void login_rsp_tgt_err(struct connection *conn, int status_detail)
{
	struct iscsi_login_rsp_hdr * const rsp =
		(struct iscsi_login_rsp_hdr * const)&conn->rsp.bhs;

	rsp->status_class = ISCSI_STATUS_TARGET_ERR;
	rsp->status_detail = status_detail;
	conn->state = STATE_EXIT;
	return;
}

static void text_scan_security(struct connection *conn)
{
	char *key, *value, *data, *nextValue;
	int datasize;

	data = conn->req.data;
	datasize = conn->req.datasize;

	while ((key = next_key(&data, &datasize, &value))) {
		if (!(params_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 (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING))
						continue;
					conn->auth_method = AUTH_NONE;
					text_key_add(conn, key, "None");
					break;
				} else if (!strcmp(value, "CHAP")) {
					if (accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING))
						continue;
					conn->auth_method = AUTH_CHAP;
					text_key_add(conn, key, "CHAP");
					break;
				}
			} while ((value = nextValue));

			if (conn->auth_method == AUTH_UNKNOWN)
				text_key_add_reject(conn, key);
		} else
			text_key_add(conn, key, "NotUnderstood");
	}
	if (conn->auth_method == AUTH_UNKNOWN)
		login_rsp_ini_err(conn, ISCSI_STATUS_AUTH_FAILED);
	return;
}

#define ISCSI_SESS_REINSTATEMENT	1
#define ISCSI_CONN_REINSTATEMENT	2

/*
 * Returns above ISCSI_*_REINSTATEMENT for session reinstatement,
 * <0 for error, 0 otherwise.
 */
static int login_check_reinstatement(struct connection *conn)
{
	struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs;
	struct session *session;
	int res = 0;

	/*
	 * We only check here to catch errors earlier. Actual session/connection
	 * reinstatement, if necessary, will be done in the kernel.
	 */

	sBUG_ON(conn->sess != NULL);

	session = session_find_name(conn->tid, conn->initiator, req->sid);
	if (session != NULL) {

		if (req->sid.id.tsih == 0) {
			struct connection *existing_conn;
			list_for_each_entry(existing_conn, &session->conn_list, clist) {
				/* Don't go for session reinstatement if IPs are different */
				if(strcmp(conn->initiator_ip_address, existing_conn->initiator_ip_address)) {
					log_info("Session sid %#" PRIx64 " Reinstatement "
						"rejected (tid %d, initiator %s, IPs [%s, %s])", req->sid.id64,
						conn->tid, conn->initiator, conn->initiator_ip_address, existing_conn->initiator_ip_address);
					/* Fail the login */
					login_rsp_ini_err(conn, ISCSI_STATUS_DUP_IQN);
					res = -1;
					goto out;
				}
			}
			/* Kernel will do session reinstatement */
			log_info("Session sid %#" PRIx64 " reinstatement "
				"detected (tid %d, initiator %s)", req->sid.id64,
				conn->tid, conn->initiator);
			res = ISCSI_SESS_REINSTATEMENT;
		} else if (req->sid.id.tsih != session->sid.id.tsih) {
			log_error("TSIH for existing session sid %#" PRIx64
				") doesn't match (tid %d, initiator %s, sid requested "
				"%#" PRIx64, session->sid.id64, conn->tid,
				conn->initiator, req->sid.id64);
			/* Fail the login */
			login_rsp_ini_err(conn, ISCSI_STATUS_SESSION_NOT_FOUND);
			res = -1;
			goto out;
		} else {
			struct connection *c = conn_find(session, conn->cid);

			if (c != NULL) {
				/* Kernel will do connection reinstatement */
				log_debug(1, "Conn %x reinstatement "
					"detected (tid %d, sid %#" PRIx64
					"initiator %s)", conn->cid, conn->tid,
					req->sid.id64, conn->initiator);
				conn->sess = session;
				list_add_tail(&conn->clist, &session->conn_list);
				res = ISCSI_CONN_REINSTATEMENT;
			} else {
				log_error("Only a single connection supported "
					"(initiator %s)", conn->initiator);
				/* Fail the login */
				login_rsp_ini_err(conn, ISCSI_STATUS_TOO_MANY_CONN);
				res = -1;
				goto out;
			}
		}
	} else {
		if (req->sid.id.tsih != 0) {
			log_error("Requested TSIH not 0 (TSIH %d, tid %d, "
				"initiator %s, sid requisted %#" PRIx64 ")",
				req->sid.id.tsih, conn->tid, conn->initiator,
				req->sid.id64);
			/* Fail the login */
			login_rsp_ini_err(conn, ISCSI_STATUS_SESSION_NOT_FOUND);
			res = -1;
			goto out;
		} else
			log_debug(1, "New session sid %#" PRIx64 "(tid %d, "
				"initiator %s)", req->sid.id64,
				conn->tid, conn->initiator);
	}

out:
	return res;
}

static void text_scan_login(struct connection *conn)
{
	char *key, *value, *data;
	int datasize, idx;

	data = conn->req.data;
	datasize = conn->req.datasize;

	while ((key = next_key(&data, &datasize, &value))) {
		if (!(params_index_by_name(key, login_keys) < 0))
			;
		else if (!strcmp(key, "AuthMethod"))
			;
		else if (!((idx = params_index_by_name(key, session_keys)) < 0)) {
			unsigned int val;
			char buf[32];

			if (idx == key_max_xmit_data_length) {
				text_key_add(conn, key, "NotUnderstood");
				continue;
			}
			if (idx == key_max_recv_data_length) {
				conn->session_params[idx].key_state = KEY_STATE_DONE;
				idx = key_max_xmit_data_length;
			};

			if (params_str_to_val(session_keys, idx, value, &val) < 0) {
				if (conn->session_params[idx].key_state == KEY_STATE_START) {
					text_key_add_reject(conn, key);
					continue;
				} else {
					login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
					goto out;
				}
			}

			if (conn->is_iser) {
				switch (idx) {
				case key_rdma_extensions:
					if (val != 1) {
						login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
						goto out;
					}
					break;
				case key_initial_r2t:
					val = 1;
					break;
				case key_immediate_data:
					val = 0;
					break;
				}
			} else if (idx == key_rdma_extensions && val != 0) {
				login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
				goto out;
			}

			params_check_val(session_keys, idx, &val);
			params_set_val(session_keys, conn->session_params, idx, &val);

			switch (conn->session_params[idx].key_state) {
			case KEY_STATE_START:
				if (iscsi_is_key_internal(idx)) {
					conn->session_params[idx].key_state = KEY_STATE_DONE;
					break;
				}
				memset(buf, 0, sizeof(buf));
				params_val_to_str(session_keys, idx, val, buf, sizeof(buf));
				text_key_add(conn, key, buf);
				conn->session_params[idx].key_state = KEY_STATE_DONE_ADDED;
				break;
			case KEY_STATE_REQUEST:
				if (val != conn->session_params[idx].val) {
					login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
					log_warning("%s %u %u\n", key,
						val, conn->session_params[idx].val);
					goto out;
				}
				conn->session_params[idx].key_state = KEY_STATE_DONE;
				break;
			case KEY_STATE_DONE_ADDED:
			case KEY_STATE_DONE:
				break;
			}
		} else
			text_key_add(conn, key, "NotUnderstood");
	}

out:
	return;
}

static int text_check_params(struct connection *conn)
{
	struct iscsi_param *p = conn->session_params;
	char buf[32];
	int i, cnt;

	for (i = 0, cnt = 0; session_keys[i].name; i++) {
		if (p[i].val != session_keys[i].rfc_def) {
			if (p[i].key_state == KEY_STATE_START) {
				log_debug(1, "Key %s was not negotiated, use RFC "
					"defined default %d",  session_keys[i].name,
					session_keys[i].rfc_def);
				p[i].val = session_keys[i].rfc_def;
				continue;
			} else if (p[i].key_state == KEY_STATE_DONE_ADDED) {
				log_debug(1, "Key %s was already added, val %d",
					session_keys[i].name, p[i].val);
				continue;
			}
			switch (conn->state) {
			case STATE_LOGIN_FULL:
			case STATE_SECURITY_FULL:
				if (iscsi_is_key_internal(i)) {
					p[i].key_state = KEY_STATE_DONE;
					continue;
				}
				break;
			case STATE_LOGIN:
				if (iscsi_is_key_internal(i))
					continue;
				memset(buf, 0, sizeof(buf));
				params_val_to_str(session_keys, i, p[i].val, buf, sizeof(buf));
				text_key_add(conn, session_keys[i].name, buf);
				if (i == key_max_recv_data_length) {
					p[i].key_state = KEY_STATE_DONE;
					continue;
				}
				p[i].key_state = KEY_STATE_REQUEST;
				break;
			default:
				if (iscsi_is_key_internal(i))
					continue;
			}
			cnt++;
		}
	}

	return cnt;
}

static int init_conn_session_params(struct connection *conn)
{
	int res = 0, i;
	struct target *target;

	target = target_find_by_id(conn->tid);
	if (target == NULL) {
		log_error("target %d not found", conn->tid);
		res = -ENOENT;
		goto out;
	}

	for (i = 0; i < session_key_last; i++)
		conn->session_params[i].val = target->session_params[i];

out:
	return res;
}

static void login_start(struct connection *conn)
{
	struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs;
	char *name, *session_type, *target_name;

	conn->cid = be16_to_cpu(req->cid);
	conn->sid.id64 = req->sid.id64;

	name = text_key_find(conn, "InitiatorName");
	if (!name) {
		login_rsp_ini_err(conn, ISCSI_STATUS_MISSING_FIELDS);
		return;
	}

	conn->initiator = strdup(name);
	if (conn->initiator == NULL) {
		log_error("Unable to duplicate initiator's name %s", name);
		login_rsp_tgt_err(conn, ISCSI_STATUS_NO_RESOURCES);
		return;
	}

	session_type = text_key_find(conn, "SessionType");
	target_name = text_key_find(conn, "TargetName");

	conn->auth_method = -1;
	conn->session_type = SESSION_NORMAL;

	if (session_type) {
		if (!strcmp(session_type, "Discovery")) {
			int ret = conn->is_discovery(conn->fd);

			if (ret) {
				login_rsp_tgt_err(conn, ISCSI_STATUS_MISSING_FIELDS);
				return;
			}
			conn->session_type = SESSION_DISCOVERY;
		} else if (strcmp(session_type, "Normal")) {
			login_rsp_ini_err(conn, ISCSI_STATUS_INV_SESSION_TYPE);
			return;
		}
	}

	if (conn->session_type == SESSION_NORMAL) {
		struct target *target;
		int err, rc;

		if (!target_name) {
			login_rsp_ini_err(conn, ISCSI_STATUS_MISSING_FIELDS);
			return;
		}

		target = target_find_by_name(target_name);
		if (target == NULL) {
			login_rsp_ini_err(conn, ISCSI_STATUS_TGT_NOT_FOUND);
			return;
		}

		conn->target = target;

		/* We may "leak" here if we have an iSCSI event on the wrong time */
		if (!iscsi_enabled) {
			log_info("Connect from %s to disabled iSCSI-SCST refused",
				name);
			login_rsp_tgt_err(conn, 0);
			conn->state = STATE_DROP;
			return;
		}

		if (!target->tgt_enabled) {
			log_info("Connect from %s to disabled target %s refused",
				name, target_name);
			login_rsp_tgt_err(conn, 0);
			conn->state = STATE_DROP;
			return;
		}

		conn->tid = target->tid;

		if (!config_initiator_access_allowed(conn->tid, conn->fd) ||
		    !target_portal_allowed(target, conn->target_portal,
							conn->initiator) ||
		    !isns_scn_access_allowed(conn->tid, name)) {
			log_info("Initiator %s not allowed to connect to "
				"target %s", name, target_name);
			login_rsp_ini_err(conn, ISCSI_STATUS_TGT_NOT_FOUND);
			return;
		}

		if (target_redirected(target, conn)) {
			struct iscsi_login_rsp_hdr *rsp =
				(struct iscsi_login_rsp_hdr *)&conn->rsp.bhs;

			log_debug(1, "Redirecting target %s login to %s:%d",
				target->name, target->redirect.addr,
				target->redirect.port);

			rsp->status_class = ISCSI_STATUS_REDIRECT;
			rsp->status_detail = target->redirect.type;
			conn->state = STATE_EXIT;
			return;
		}

		err = init_conn_session_params(conn);
		if (err != 0) {
			log_error("Can't get session params for session 0x%" PRIx64
				" (err %d): %s\n", conn->sid.id64, err,
				strerror(-err));
			login_rsp_tgt_err(conn, ISCSI_STATUS_TARGET_ERROR);
			return;
		}

		rc = login_check_reinstatement(conn);
		if (rc < 0)
			return;
		else if (rc == ISCSI_SESS_REINSTATEMENT) {
			target->sessions_count++;
			conn->sessions_count_incremented = 1;
		} else if (rc != ISCSI_CONN_REINSTATEMENT) {
			if ((target->target_params[key_max_sessions] == 0) ||
			    (target->sessions_count < target->target_params[key_max_sessions])) {
				target->sessions_count++;
				conn->sessions_count_incremented = 1;
			} else {
				log_warning("Initiator %s not allowed to connect to "
					"target %s - max sessions limit "
					"reached (%d)",	name, target_name,
					target->target_params[key_max_sessions]);
				login_rsp_tgt_err(conn, ISCSI_STATUS_NO_RESOURCES);
				conn->state = STATE_EXIT;
				return;
			}
		}
		log_debug(1, "target %s, sessions_count %d", target_name,
			target->sessions_count);
	}

	conn->exp_cmd_sn = be32_to_cpu(req->cmd_sn);
	log_debug(1, "exp_cmd_sn %u, cmd_sn %u", conn->exp_cmd_sn, req->cmd_sn);
	text_key_add(conn, "TargetPortalGroupTag", "1");
	return;
}

static int login_finish(struct connection *conn)
{
	int res = 0;

	if (conn->is_iser &&
	    conn->session_params[key_target_recv_data_length].key_state == KEY_STATE_START) {
		char buf[32] = "\0";

		params_val_to_str(session_keys, key_target_recv_data_length,
				  session_keys[key_target_recv_data_length].local_def,
				  buf, sizeof(buf));
		text_key_add(conn, "TargetRecvDataSegmentLength", buf);
	}

	switch (conn->session_type) {
	case SESSION_NORMAL:
		if (!conn->sess)
			res = session_create(conn);
		if (res == 0)
			conn->sid = conn->sess->sid;
		break;
	case SESSION_DISCOVERY:
		/* set a dummy tsih value */
		conn->sid.id.tsih = 1;
		break;
	}

	return res;
}

static void cmnd_reject(struct connection *conn, u8 reason)
{
	struct iscsi_reject_hdr *rej =
		(struct iscsi_reject_hdr *)&conn->rsp.bhs;
	size_t data_sz = sizeof(struct iscsi_hdr);
	struct buf_segment *seg;

	conn_free_rsp_buf_list(conn);
	seg = conn_alloc_buf_segment(conn, data_sz);

	memset(rej, 0x0, sizeof(*rej));
	rej->opcode = ISCSI_OP_REJECT_MSG;
	rej->reason = reason;
	rej->ffffffff = ISCSI_RESERVED_TAG;
	rej->flags |= ISCSI_FLG_FINAL;

	rej->stat_sn = cpu_to_be32(conn->stat_sn++);
	rej->exp_cmd_sn = cpu_to_be32(conn->exp_cmd_sn);
	rej->max_cmd_sn = cpu_to_be32(conn->exp_cmd_sn + 1);

	if (!seg) {
		log_error("Failed to alloc data segment for Reject PDU\n");
		return;
	}

	memcpy(seg->data, &conn->req.bhs, data_sz);
	seg->len = data_sz;
}

static int cmnd_exec_auth(struct connection *conn)
{
	int res;

	switch (conn->auth_method) {
	case AUTH_CHAP:
		res = cmnd_exec_auth_chap(conn);
		break;
	case AUTH_NONE:
		res = 0;
		break;
	default:
		log_error("Unknown auth. method %d", conn->auth_method);
		res = -3;
	}

	return res;
}

static void cmnd_exec_login(struct connection *conn)
{
	struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs;
	struct iscsi_login_rsp_hdr *rsp = (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs;
	int stay = 0, nsg_disagree = 0;

	memset(rsp, 0, BHS_SIZE);
	if ((req->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_LOGIN_CMD ||
	    !(req->opcode & ISCSI_OP_IMMEDIATE)) {
		cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
		return;
	}

	rsp->opcode = ISCSI_OP_LOGIN_RSP;
	rsp->max_version = ISCSI_VERSION;
	rsp->active_version = ISCSI_VERSION;
	rsp->itt = req->itt;

	if (/*req->max_version < ISCSI_VERSION ||*/
	    req->min_version > ISCSI_VERSION) {
		login_rsp_ini_err(conn, ISCSI_STATUS_NO_VERSION);
		return;
	}

	switch (req->flags & ISCSI_FLG_CSG_MASK) {
	case ISCSI_FLG_CSG_SECURITY:
		log_debug(1, "Login request (security negotiation): %d", conn->state);
		rsp->flags = ISCSI_FLG_CSG_SECURITY;

		switch (conn->state) {
		case STATE_FREE:
			conn->state = STATE_SECURITY;
			login_start(conn);
			if (rsp->status_class)
				return;
			/* else fall through */
		case STATE_SECURITY:
			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;
			}
			break;
		case STATE_SECURITY_AUTH:
			switch (cmnd_exec_auth(conn)) {
			case 0:
				break;
			default:
			case -1:
				goto init_err;
			case -2:
				goto auth_err;
			}
			break;
		default:
			goto init_err;
		}

		break;
	case ISCSI_FLG_CSG_LOGIN:
		log_debug(1, "Login request (operational negotiation): %d", conn->state);
		rsp->flags = ISCSI_FLG_CSG_LOGIN;

		switch (conn->state) {
		case STATE_FREE:
			conn->state = STATE_LOGIN;

			login_start(conn);
			if (rsp->status_class)
				return;
			if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING))
				goto auth_err;
			if (rsp->status_class)
				return;
			text_scan_login(conn);
			if (rsp->status_class)
				return;
			stay = text_check_params(conn);
			break;
		case STATE_LOGIN:
			text_scan_login(conn);
			if (rsp->status_class)
				return;
			stay = text_check_params(conn);
			break;
		default:
			goto init_err;
		}
		break;
	default:
		goto init_err;
	}

	if (rsp->status_class)
		return;
	if (conn->state != STATE_SECURITY_AUTH && req->flags & ISCSI_FLG_TRANSIT) {
		int nsg = req->flags & ISCSI_FLG_NSG_MASK;

		switch (nsg) {
		case ISCSI_FLG_NSG_LOGIN:
			switch (conn->state) {
			case STATE_SECURITY:
			case STATE_SECURITY_DONE:
				conn->state = STATE_SECURITY_LOGIN;
				break;
			default:
				goto init_err;
			}
			break;
		case ISCSI_FLG_NSG_FULL_FEATURE:
			switch (conn->state) {
			case STATE_SECURITY:
			case STATE_SECURITY_DONE:
				if ((nsg_disagree = text_check_params(conn))) {
					conn->state = STATE_LOGIN;
					nsg = ISCSI_FLG_NSG_LOGIN;
					break;
				}
				conn->state = STATE_SECURITY_FULL;
				break;
			case STATE_LOGIN:
				if (stay)
					nsg = ISCSI_FLG_NSG_LOGIN;
				else
					conn->state = STATE_LOGIN_FULL;
				break;
			default:
				goto init_err;
			}
			if (!stay && !nsg_disagree) {
				int err;

				text_check_params(conn);
				err = login_finish(conn);
				if (err != 0) {
					log_debug(1, "login_finish() failed: %d", err);
					/* Make initiator retry later */
					goto tgt_no_mem;
				}
			}
			break;
		default:
			goto init_err;
		}
		rsp->flags |= nsg | (stay ? 0 : ISCSI_FLG_TRANSIT);
	}

	/*
	 * TODO: support Logical Text Data Segments > INCOMING_BUFSIZE (i.e.
	 * key=value pairs spanning several PDUs) during login phase
	 */
	if (!list_empty(&conn->rsp_buf_list) &&
	    !list_length_is_one(&conn->rsp_buf_list)) {
		log_error("Target error: \'key=value\' pairs spanning several "
			  "Login PDUs are not implemented, yet\n");
		goto target_err;
	}

	rsp->sid = conn->sid;
	rsp->stat_sn = cpu_to_be32(conn->stat_sn++);
	rsp->exp_cmd_sn = cpu_to_be32(conn->exp_cmd_sn);
	rsp->max_cmd_sn = cpu_to_be32(conn->exp_cmd_sn + 1);
	return;

init_err:
	log_error("Initiator %s error", conn->initiator);
	rsp->flags = 0;
	login_rsp_ini_err(conn, ISCSI_STATUS_INIT_ERR);
	return;

auth_err:
	log_error("Authentication of initiator %s failed", conn->initiator);
	rsp->flags = 0;
	login_rsp_ini_err(conn, ISCSI_STATUS_AUTH_FAILED);
	return;

target_err:
	rsp->flags = 0;
	login_rsp_tgt_err(conn, ISCSI_STATUS_TARGET_ERROR);
	return;

tgt_no_mem:
	rsp->flags = 0;
	login_rsp_tgt_err(conn, ISCSI_STATUS_NO_RESOURCES);
	return;
}

static int text_scan_text(struct connection *conn)
{
	int res = 0;
	char *key, *value, *data;
	int datasize;

	data = conn->req.data;
	datasize = conn->req.datasize;

	while ((key = next_key(&data, &datasize, &value))) {
		if (!strcmp(key, "SendTargets")) {
			if (value[0] == '\0')
				value = conn->sess->target->name;
			else if (strcasecmp(value, "All") == 0) {
				if (conn->session_type != SESSION_DISCOVERY) {
					log_error("SendTargets=All allowed only in "
						"Discovery session, rejecting "
						"(initiator %s)", conn->initiator);
					cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
					res = -EINVAL;
					goto out;
				}
			}

			target_list_build(conn,
					  strcmp(value, "All") ? value : NULL);
		} else
			text_key_add(conn, key, "NotUnderstood");
	}

out:
	return res;
}

static void cmnd_exec_text(struct connection *conn)
{
	struct iscsi_text_req_hdr *req = (struct iscsi_text_req_hdr *)&conn->req.bhs;
	struct iscsi_text_rsp_hdr *rsp = (struct iscsi_text_rsp_hdr *)&conn->rsp.bhs;
	int rc;

	memset(rsp, 0, BHS_SIZE);

	rsp->opcode = ISCSI_OP_TEXT_RSP;
	rsp->itt = req->itt;
	conn->exp_cmd_sn = be32_to_cpu(req->cmd_sn);
	if (!(req->opcode & ISCSI_OP_IMMEDIATE))
		conn->exp_cmd_sn++;

	log_debug(1, "Text request: %d", conn->state);

	if (req->ttt == ISCSI_RESERVED_TAG) {
		conn_free_rsp_buf_list(conn);
		rc = text_scan_text(conn);
		if (rc != 0)
			goto out;
		if (!list_empty(&conn->rsp_buf_list) &&
		    !list_length_is_one(&conn->rsp_buf_list))
			conn->ttt = get_next_ttt(conn);
		else
			conn->ttt = ISCSI_RESERVED_TAG;
	} else if (list_empty(&conn->rsp_buf_list) || conn->ttt != req->ttt) {
		log_error("Rejecting unexpected text request. TTT recv %#x, "
			  "expected %#x; %stext segments queued\n",
			  req->ttt, conn->ttt, list_empty(&conn->rsp_buf_list) ?
			  "no " : "");
		cmnd_reject(conn, ISCSI_REASON_INVALID_PDU_FIELD);
		return;
	}

	if (list_empty(&conn->rsp_buf_list) ||
	    list_length_is_one(&conn->rsp_buf_list)) {
		rsp->flags = ISCSI_FLG_FINAL;
		conn->ttt = ISCSI_RESERVED_TAG;
	}

	rsp->ttt = conn->ttt;

	rsp->stat_sn = cpu_to_be32(conn->stat_sn++);
	rsp->exp_cmd_sn = cpu_to_be32(conn->exp_cmd_sn);
	rsp->max_cmd_sn = cpu_to_be32(conn->exp_cmd_sn + 1);

out:
	return;
}

static void cmnd_exec_logout(struct connection *conn)
{
	struct iscsi_logout_req_hdr *req = (struct iscsi_logout_req_hdr *)&conn->req.bhs;
	struct iscsi_logout_rsp_hdr *rsp = (struct iscsi_logout_rsp_hdr *)&conn->rsp.bhs;

	memset(rsp, 0, BHS_SIZE);
	rsp->opcode = ISCSI_OP_LOGOUT_RSP;
	rsp->flags = ISCSI_FLG_FINAL;
	rsp->itt = req->itt;
	conn->exp_cmd_sn = be32_to_cpu(req->cmd_sn);
	if (!(req->opcode & ISCSI_OP_IMMEDIATE))
		conn->exp_cmd_sn++;

	rsp->stat_sn = cpu_to_be32(conn->stat_sn++);
	rsp->exp_cmd_sn = cpu_to_be32(conn->exp_cmd_sn);
	rsp->max_cmd_sn = cpu_to_be32(conn->exp_cmd_sn + 1);
}

int cmnd_execute(struct connection *conn)
{
	int res = 1;
	struct buf_segment *seg;
	struct iscsi_login_rsp_hdr *login_rsp;

	switch (conn->req.bhs.opcode & ISCSI_OPCODE_MASK) {
	case ISCSI_OP_LOGIN_CMD:
		if (conn->state == STATE_FULL) {
			cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
			break;
		}
		cmnd_exec_login(conn);
		login_rsp = (struct iscsi_login_rsp_hdr *) &conn->rsp.bhs;
		if (login_rsp->status_class && login_rsp->status_class != ISCSI_STATUS_REDIRECT)
			conn_free_rsp_buf_list(conn);
		break;
	case ISCSI_OP_TEXT_CMD:
		if (conn->state != STATE_FULL)
			cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
		else
			cmnd_exec_text(conn);
		break;
	case ISCSI_OP_LOGOUT_CMD:
		if (conn->state != STATE_FULL)
			cmnd_reject(conn, ISCSI_REASON_PROTOCOL_ERROR);
		else
			cmnd_exec_logout(conn);
		break;
	default:
		cmnd_reject(conn, ISCSI_REASON_UNSUPPORTED_COMMAND);
		res = 0;
		goto out;
	}

	if (!list_empty(&conn->rsp_buf_list)) {
		seg = list_entry(conn->rsp_buf_list.q_forw,
				 struct buf_segment, entry);
		list_del_init(&seg->entry);
		conn->rsp.datasize = seg->len;
		conn->rsp.data = seg->data;
	} else {
		conn->rsp.datasize = 0;
		conn->rsp.data = NULL;
	}

	conn->rsp.bhs.ahslength = conn->rsp.ahssize / 4;
	conn->rsp.bhs.datalength[0] = conn->rsp.datasize >> 16;
	conn->rsp.bhs.datalength[1] = conn->rsp.datasize >> 8;
	conn->rsp.bhs.datalength[2] = conn->rsp.datasize;
	log_pdu(2, &conn->rsp);

out:
	return res;
}

void cmnd_finish(struct connection *conn)
{
	struct buf_segment *seg;

	if (conn->rsp.data) {
		seg = container_of(conn->rsp.data, struct buf_segment, data);
		list_del(&seg->entry);
		free(seg);
		conn->rsp.data = NULL;
	}

	switch (conn->state) {
	case STATE_EXIT:
	case STATE_DROP:
		break;
	case STATE_SECURITY_LOGIN:
		conn->state = STATE_LOGIN;
		break;
	case STATE_SECURITY_FULL:
		/* fall through */
	case STATE_LOGIN_FULL:
		if (conn->session_type == SESSION_NORMAL)
			conn->state = STATE_KERNEL;
		else
			conn->state = STATE_FULL;
		break;
	}
}
