/*
 *  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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <netdb.h>
#include <signal.h>

#include <poll.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/ioctl.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

#include "iscsid.h"
#include "iscsi_adm.h"

static char *server_address;
uint16_t server_port = ISCSI_LISTEN_PORT;

struct pollfd poll_array[POLL_MAX];

static struct connection *incoming[INCOMING_MAX];
static int incoming_cnt;
int ctrl_fd, ipc_fd, nl_fd;
int conn_blocked;

struct iscsi_init_params iscsi_init_params;

static const char program_name[] = "iscsi-scstd";

static struct option const long_options[] = {
	{"config", required_argument, 0, 'c'},
	{"foreground", no_argument, 0, 'f'},
	{"debug", required_argument, 0, 'd'},
	{"uid", required_argument, 0, 'u'},
	{"gid", required_argument, 0, 'g'},
	{"address", required_argument, 0, 'a'},
	{"port", required_argument, 0, 'p'},
	{"version", no_argument, 0, 'v'},
	{"help", no_argument, 0, 'h'},
	{0, 0, 0, 0},
};

int init_report_pipe[2];

static void usage(int status)
{
	if (status != 0)
		fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
	else {
		printf("Usage: %s [OPTION]\n", program_name);
		printf("\
iSCSI target daemon.\n\
  -c, --config=[path]     Execute in the config file.\n");
		printf("\
  -f, --foreground        make the program run in the foreground\n\
  -d, --debug debuglevel  print debugging information\n\
  -u, --uid=uid           run as uid, default is current user\n\
  -g, --gid=gid           run as gid, default is current user group\n\
  -a, --address=address   listen on specified local address instead of all\n\
  -p, --port=port         listen on specified port instead of 3260\n\
  -h, --help              display this help and exit\n\
");
	}
	exit(1);
}

const char *get_error_str(int error)
{
	if (error == EAI_SYSTEM)
		return strerror(errno);
	else
		return gai_strerror(error);
}

static void create_listen_socket(struct pollfd *array)
{
	struct addrinfo hints, *res, *res0;
	char servname[64];
	int i, sock, opt, rc;

	memset(servname, 0, sizeof(servname));
	snprintf(servname, sizeof(servname), "%d", server_port);

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;

	rc = getaddrinfo(server_address, servname, &hints, &res0);
	if (rc != 0) {
		log_error("Unable to get address info (%s)!",
			get_error_str(rc));
		exit(1);
	}

	i = 0;
	for (res = res0; res && i < LISTEN_MAX; res = res->ai_next) {
		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sock < 0) {
			log_error("Unable to create server socket (%s) %d %d %d!",
				  strerror(errno), res->ai_family,
				  res->ai_socktype, res->ai_protocol);
			continue;
		}

		sock_set_keepalive(sock, 50);

		opt = 1;
		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
			log_warning("Unable to set SO_REUSEADDR on server socket (%s)!",
				    strerror(errno));
		opt = 1;
		if (res->ai_family == AF_INET6 &&
		    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))) {
			log_error("Unable to restrict IPv6 socket (%s)", strerror(errno));
			close(sock);
			continue;
		}

		if (bind(sock, res->ai_addr, res->ai_addrlen)) {
			log_error("Unable to bind server socket (%s)!", strerror(errno));
			close(sock);
			continue;
		}

		if (listen(sock, INCOMING_MAX)) {
			log_error("Unable to listen to server socket (%s)!", strerror(errno));
			close(sock);
			continue;
		}

		set_non_blocking(sock);

		array[i].fd = sock;
		array[i].events = POLLIN;

		i++;
	}

	freeaddrinfo(res0);

	if (i == 0)
		exit(1);
}

static struct connection *alloc_and_init_conn(int fd)
{
	struct pollfd *pollfd;
	struct connection *conn = NULL;
	int i;

	for (i = 0; i < INCOMING_MAX; i++) {
		if (!incoming[i])
			break;
	}
	if (i >= INCOMING_MAX) {
		log_error("Unable to find incoming slot? %d\n", i);
		goto out;
	}

	conn = conn_alloc();
	if (!conn) {
		log_error("Fail to allocate %s", "conn\n");
		goto out;
	}

	conn->fd = fd;
	incoming[i] = conn;

	pollfd = &poll_array[POLL_INCOMING + i];
	pollfd->fd = fd;
	pollfd->events = POLLIN;
	pollfd->revents = 0;

	conn_read_pdu(conn);
	set_non_blocking(fd);

out:
	return conn;
}

static int transmit_iser(int fd, bool start)
{
	int opt = start;

	return ioctl(fd, RDMA_CORK, &opt, sizeof(opt));
}

static int cork_transmit_iser(int fd)
{
	return transmit_iser(fd, true);
}

static int uncork_transmit_iser(int fd)
{
	return transmit_iser(fd, false);
}

static void create_iser_listen_socket(struct pollfd *array)
{
	struct addrinfo hints, *res, *res0;
	char servname[64];
	int rc, i;
	int iser_fd;
	struct isert_addr_info info;

	iser_fd = create_and_open_dev("isert_scst", 1);

	if (iser_fd >= 0) {
		poll_array[POLL_ISER_LISTEN].fd = iser_fd;
		poll_array[POLL_ISER_LISTEN].events = POLLIN;

		/* RDMAExtensions */
		session_keys[key_rdma_extensions].max = 1;
		session_keys[key_rdma_extensions].local_def = 1;
	} else {
		poll_array[POLL_ISER_LISTEN].fd = -1;
		poll_array[POLL_ISER_LISTEN].events = 0;
		return;
	}

	memset(servname, 0, sizeof(servname));
	snprintf(servname, sizeof(servname), "%d", server_port);

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;

	rc = getaddrinfo(server_address, servname, &hints, &res0);
	if (rc != 0) {
		log_error("Unable to get address info (%s)!",
			get_error_str(rc));
		exit(1);
	}

	i = 0;
	for (res = res0; res && i < ISERT_MAX_PORTALS; res = res->ai_next) {
		memcpy(&info.addr, res->ai_addr, res->ai_addrlen);
		info.addr_len = res->ai_addrlen;

		rc = ioctl(iser_fd, SET_LISTEN_ADDR, &info);
		if (rc != 0) {
			log_error("Unable to set listen address (%s)!",
				strerror(errno));
		}
		++i;
	}

	freeaddrinfo(res0);
}

static int iser_getsockname(int fd, struct sockaddr *name, socklen_t *namelen)
{
	struct isert_addr_info addr;
	int ret;

	ret = ioctl(fd, GET_PORTAL_ADDR, &addr, sizeof(addr));
	if (ret)
		return ret;

	memcpy(name, &addr.addr, addr.addr_len);
	*namelen = addr.addr_len;

	return ret;
}

static int iser_is_discovery(int fd)
{
	int val = 1;

	return ioctl(fd, DISCOVERY_SESSION, &val, sizeof(val));
}

static void iser_accept(int fd)
{
	char buff[256];
	int ret, conn_fd;
	struct connection *conn;
	char target_portal[ISCSI_PORTAL_LEN], target_portal_port[NI_MAXSERV];
	struct isert_addr_info addr;

	ret = read(fd, buff, sizeof(buff));
	if (ret == -1)
		goto out;

	conn_fd = open(buff, O_RDWR);
	if (conn_fd == -1) {
		log_error("open(iser_connection) %s failed: %s\n",
			buff, strerror(errno));
		goto out;
	}

	ret = ioctl(conn_fd, GET_PORTAL_ADDR, &addr, sizeof(addr));
	if (ret) {
		log_error("ioctl(GET_PORTAL_ADDR) failed: %s\n",
			  strerror(errno));
		goto out_close;
	}

	ret = getnameinfo((struct sockaddr *)&addr, sizeof(addr), target_portal,
			 sizeof(target_portal), target_portal_port,
			 sizeof(target_portal_port),
			 NI_NUMERICHOST | NI_NUMERICSERV);
	if (ret != 0) {
		log_error("Target portal getnameinfo() failed: %s!",
			get_error_str(ret));
		goto out_close;
	}

	log_info("iSER Connect to %s:%s", target_portal, target_portal_port);

	if (conn_blocked) {
		log_warning("Connection refused due to blocking\n");
		goto out_close;
	}

	conn = alloc_and_init_conn(conn_fd);
	if (!conn)
		goto out_close;

	conn->target_portal = strdup(target_portal);
	if (conn->target_portal == NULL) {
		log_error("Unable to duplicate target portal %s", target_portal);
		goto out_free;
	}

	conn->cork_transmit = cork_transmit_iser;
	conn->uncork_transmit = uncork_transmit_iser;
	conn->getsockname = iser_getsockname;
	conn->is_discovery = iser_is_discovery;
	conn->is_iser = true;
	incoming_cnt++;

out:
	return;

out_free:
	conn_free(conn);

out_close:
	close(conn_fd);
	goto out;
}

static int transmit_sock(int fd, bool start)
{
	int opt = start;

	return setsockopt(fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
}

static int cork_transmit_sock(int fd)
{
	return transmit_sock(fd, true);
}

static int uncork_transmit_sock(int fd)
{
	return transmit_sock(fd, false);
}

static int tcp_is_discovery(int fd)
{
	return 0;
}

static void accept_connection(int listen)
{
	union {
		struct sockaddr sa;
		struct sockaddr_in sin;
		struct sockaddr_in6 sin6;
	} from, to;
	socklen_t namesize;
	struct connection *conn;
	int fd, rc;
	char initiator_addr[ISCSI_PORTAL_LEN], initiator_port[NI_MAXSERV];
	char target_portal[ISCSI_PORTAL_LEN], target_portal_port[NI_MAXSERV];

	namesize = sizeof(from);
	if ((fd = accept(listen, &from.sa, &namesize)) < 0) {
		switch (errno) {
		case EINTR:
		case EAGAIN:
		case ENETDOWN:
		case EPROTO:
		case ENOPROTOOPT:
		case EHOSTDOWN:
		case ENONET:
		case EHOSTUNREACH:
		case EOPNOTSUPP:
		case ENETUNREACH:
			break;
		default:
			log_error("accept(incoming_socket) failed: %s",
				strerror(errno));
			exit(1);
		}
		goto out;
	}

	namesize = sizeof(to);
	rc = getsockname(fd, &to.sa, &namesize);
	if (rc != 0) {
		log_error("getsockname() failed: %s", strerror(errno));
		goto out_close;
	}

	rc = getnameinfo(&to.sa, sizeof(to), target_portal, sizeof(target_portal),
		target_portal_port, sizeof(target_portal_port),
		NI_NUMERICHOST | NI_NUMERICSERV);
	if (rc != 0) {
		log_error("Target portal getnameinfo() failed: %s!",
			get_error_str(rc));
		goto out_close;
	}

	rc = getnameinfo(&from.sa, sizeof(from), initiator_addr,
		 sizeof(initiator_addr), initiator_port,
		 sizeof(initiator_port), NI_NUMERICHOST | NI_NUMERICSERV);
	if (rc != 0) {
		log_error("Initiator getnameinfo() failed: %s!",
			get_error_str(rc));
		goto out_close;
	}

	log_info("Connect from %s:%s to %s:%s", initiator_addr, initiator_port,
		target_portal, target_portal_port);

	if (conn_blocked) {
		log_warning("Connection refused due to blocking\n");
		goto out_close;
	}

	conn = alloc_and_init_conn(fd);
	if (!conn)
		goto out_close;

	conn->target_portal = strdup(target_portal);
	if (conn->target_portal == NULL) {
		log_error("Unable to duplicate target portal %s", target_portal);
		goto out_free;
	}

	conn->initiator_ip_address = strdup(initiator_addr);
	if (conn->initiator_ip_address == NULL) {
		log_error("Unable to duplicate initiator address %s", initiator_addr);
		goto out_free;
	}
	
	conn->cork_transmit = cork_transmit_sock;
	conn->uncork_transmit = uncork_transmit_sock;
	conn->getsockname = getsockname;
	conn->is_discovery = tcp_is_discovery;
	conn_read_pdu(conn);

	incoming_cnt++;

out:
	return;

out_free:
	conn_free(conn);

out_close:
	close(fd);
	goto out;
}

static void __set_fd(int idx, int fd)
{
	poll_array[idx].fd = fd;
	poll_array[idx].events = fd ? POLLIN : 0;
}

void isns_set_fd(int isns, int scn_listen, int scn)
{
	__set_fd(POLL_ISNS, isns);
	__set_fd(POLL_SCN_LISTEN, scn_listen);
	__set_fd(POLL_SCN, scn);
}

static void event_conn(struct connection *conn, struct pollfd *pollfd)
{
	int res;

again:
	switch (conn->iostate) {
	case IOSTATE_READ_BHS:
	case IOSTATE_READ_AHS_DATA:
	      read_again:
		errno = 0;	/* for the log_debug() */
		res = read(pollfd->fd, conn->buffer, conn->rwsize);
		if (res <= 0) {
			log_debug(1, "read(%u, %p, %u) returned %d, errno=%u",
			      pollfd->fd, conn->buffer, conn->rwsize, res, errno);
			if (res == 0 || (errno != EINTR && errno != EAGAIN)) {
				conn->state = STATE_DROP;
				goto out;
			} else if (errno == EINTR)
				goto read_again;
			break;
		}
		conn->rwsize -= res;
		conn->buffer += res;
		if (conn->rwsize)
			break;

		switch (conn->iostate) {
		case IOSTATE_READ_BHS:
			conn->iostate = IOSTATE_READ_AHS_DATA;
			conn->req.ahssize = conn->req.bhs.ahslength * 4;
			conn->req.datasize = ((conn->req.bhs.datalength[0] << 16) +
					      (conn->req.bhs.datalength[1] << 8) +
					      conn->req.bhs.datalength[2]);
			conn->rwsize = (conn->req.ahssize + conn->req.datasize + 3) & -4;
			if (conn->rwsize > INCOMING_BUFSIZE) {
				log_warning("Recv PDU with invalid size %d "
					"(max: %d)", conn->rwsize,
					INCOMING_BUFSIZE);
				conn->state = STATE_DROP;
				goto out;
			}
			if (conn->rwsize) {
				if (!conn->req_buffer) {
					conn->req_buffer = malloc(INCOMING_BUFSIZE);
					if (!conn->req_buffer) {
						log_error("Failed to alloc recv buffer");
						conn->state = STATE_DROP;
						goto out;
					}
				}
				conn->buffer = conn->req_buffer;
				conn->req.ahs = conn->buffer;
				conn->req.data = conn->buffer + conn->req.ahssize;
				goto read_again;
			}
			/* fall-through */

		case IOSTATE_READ_AHS_DATA:
			conn_write_pdu(conn);
			pollfd->events = POLLOUT;

			log_pdu(2, &conn->req);
			if (!cmnd_execute(conn))
				conn->state = STATE_EXIT;

			if (conn->state == STATE_EXIT) {
				/* We need to send response */
				goto again;
			}
			break;
		}
		break;

	case IOSTATE_WRITE_BHS:
	case IOSTATE_WRITE_AHS:
	case IOSTATE_WRITE_DATA:
	      write_again:
		conn->cork_transmit(pollfd->fd);
		res = write(pollfd->fd, conn->buffer, conn->rwsize);
		if (res < 0) {
			log_debug(1, "write(%u, %p, %u) returned %d, errno=%u",
			      pollfd->fd, conn->buffer, conn->rwsize, res, errno);
			if (errno != EINTR && errno != EAGAIN) {
				conn->state = STATE_DROP;
				goto out;
			} else if (errno == EINTR)
				goto write_again;
			break;
		}

		conn->rwsize -= res;
		conn->buffer += res;
		if (conn->rwsize)
			goto write_again;

		switch (conn->iostate) {
		case IOSTATE_WRITE_BHS:
			if (conn->rsp.ahssize) {
				conn->iostate = IOSTATE_WRITE_AHS;
				conn->buffer = conn->rsp.ahs;
				conn->rwsize = conn->rsp.ahssize;
				goto write_again;
			}
			/* fall-through */
		case IOSTATE_WRITE_AHS:
			if (conn->rsp.datasize) {
				int o;

				conn->iostate = IOSTATE_WRITE_DATA;
				conn->buffer = conn->rsp.data;
				conn->rwsize = conn->rsp.datasize;
				o = conn->rwsize & 3;
				if (o) {
					for (o = 4 - o; o; o--)
						*((u8 *) conn->buffer + conn->rwsize++) =
						    0;
				}
				goto write_again;
			}
			/* fall-through */
		case IOSTATE_WRITE_DATA:
			conn->uncork_transmit(pollfd->fd);
			cmnd_finish(conn);

			switch (conn->state) {
			case STATE_KERNEL:
				conn_pass_to_kern(conn, pollfd->fd);
				if (conn->passed_to_kern)
					conn->state = STATE_CLOSE;
				else
					conn->state = STATE_EXIT;
				break;
			case STATE_EXIT:
			case STATE_CLOSE:
			case STATE_DROP:
				break;
			default:
				conn_read_pdu(conn);
				pollfd->events = POLLIN;
				break;
			}
			break;
		}

		break;
	default:
		log_error("illegal iostate %d for port %d!\n", conn->iostate,
			pollfd->fd);
		exit(1);
	}
out:
	return;
}

static void event_loop(void)
{
	int res, i;

	create_listen_socket(poll_array + POLL_LISTEN);
	create_iser_listen_socket(poll_array);

	poll_array[POLL_IPC].fd = ipc_fd;
	poll_array[POLL_IPC].events = POLLIN;
	poll_array[POLL_NL].fd = nl_fd;
	poll_array[POLL_NL].events = POLLIN;

	for (i = 0; i < INCOMING_MAX; i++) {
		poll_array[POLL_INCOMING + i].fd = -1;
		poll_array[POLL_INCOMING + i].events = 0;
		incoming[i] = NULL;
	}

	close(init_report_pipe[0]);
	res = 0;

	if (log_daemon)
		res = write(init_report_pipe[1], &res, sizeof(res));

	close(init_report_pipe[1]);

	while (1) {
		if (!iscsi_enabled) {
			handle_iscsi_events(nl_fd, true);
			continue;
		}
		res = poll(poll_array, POLL_MAX, isns_timeout);
		if (res == 0) {
			isns_handle(1);
			continue;
		} else if (res < 0) {
			if (errno == EINTR)
				continue;
			else if (errno == EINVAL)
				log_error("%s: poll() failed with EINVAL. Should "
					"you increase RLIMIT_NOFILE (ulimit -n)? "
					"Or upgrade your kernel? Kernels below 2.6.19 "
					"have a bug, which doesn't allow poll() "
					"to work with >256 file descriptors. See "
					"http://sourceforge.net/mailarchive/forum.php?"
					"thread_name=9392A06CB0FDC847B3A530B3DC174E7B0"
					"55F1EF3%40mse10be1.mse10.exchange.ms&forum_"
					"name=scst-devel for more details. Alternatively, "
					"you can decrease iscsi_scstd.c::INCOMING_MAX "
					"constant to a lower value, e.g. 128, then "
					"recompile and reinstall the user space part "
					"of iSCSI-SCST.", __func__);
			else
				log_error("%s: poll() failed: %s", __func__,
					strerror(errno));
			exit(1);
		}

		for (i = 0; i < LISTEN_MAX; i++) {
			if (poll_array[POLL_LISTEN + i].revents
			    && incoming_cnt < INCOMING_MAX)
				accept_connection(poll_array[POLL_LISTEN + i].fd);
		}

		if (poll_array[POLL_NL].revents)
			handle_iscsi_events(nl_fd, false);

		if (poll_array[POLL_IPC].revents)
			iscsi_adm_request_handle(ipc_fd);

		if (poll_array[POLL_ISNS].revents)
			isns_handle(0);

		if (poll_array[POLL_SCN_LISTEN].revents)
			isns_scn_handle(1);

		if (poll_array[POLL_SCN].revents)
			isns_scn_handle(0);

		if (poll_array[POLL_ISER_LISTEN].revents)
			iser_accept(poll_array[POLL_ISER_LISTEN].fd);

		for (i = 0; i < INCOMING_MAX; i++) {
			struct connection *conn = incoming[i];
			struct pollfd *pollfd = &poll_array[POLL_INCOMING + i];

			if (!conn || !pollfd->revents)
				continue;

			pollfd->revents = 0;

			event_conn(conn, pollfd);

			if ((conn->state == STATE_CLOSE) ||
			    (conn->state == STATE_EXIT) ||
			    (conn->state == STATE_DROP)) {
				struct session *sess = conn->sess;

				log_debug(1, "closing conn %p state=0x%x fd=%u",
					  conn, conn->state, pollfd->fd);
				conn_free_pdu(conn);
				close(pollfd->fd);
				pollfd->fd = -1;
				incoming[i] = NULL;
				incoming_cnt--;
				if (conn->state != STATE_CLOSE) {
					if (conn->passed_to_kern) {
						kernel_conn_destroy(conn->tid,
							conn->sess->sid.id64,
							conn->cid);
					} else {
						/*
						 * Check if session could not be established,
						 * but sessions count was already incremented
						 */
						if (!sess && conn->sessions_count_incremented)
							conn->target->sessions_count--;
						log_debug(1, "conn %p freed (sess %p, empty %d)",
							conn, sess,
							sess ? list_empty(&sess->conn_list) : -1);
						conn_free(conn);
						if (sess && list_empty(&sess->conn_list))
							session_free(sess);
					}
				}
			}
		}
	}
}

static void init_max_params(void)
{
	if ((session_keys[key_max_recv_data_length].local_def != -1) ||
	    (session_keys[key_max_recv_data_length].max != -1) ||
	    (session_keys[key_max_xmit_data_length].local_def != -1) ||
	    (session_keys[key_max_xmit_data_length].max != -1) ||
	    (session_keys[key_max_burst_length].local_def != -1) ||
	    (session_keys[key_max_burst_length].max != -1) ||
	    (session_keys[key_first_burst_length].max != -1)) {
		log_error("Wrong session_keys initialization");
		exit(-1);
	}

	/* QueuedCommands */
	target_keys[key_queued_cmnds].local_def = min((int)target_keys[key_queued_cmnds].local_def,
						      iscsi_init_params.max_queued_cmds);
	target_keys[key_queued_cmnds].max = min((int)target_keys[key_queued_cmnds].max,
						iscsi_init_params.max_queued_cmds);
	target_keys[key_queued_cmnds].min = min((int)target_keys[key_queued_cmnds].min,
						iscsi_init_params.max_queued_cmds);

	/* MaxRecvDataSegmentLength */
	session_keys[key_max_recv_data_length].local_def = iscsi_init_params.max_data_seg_len;
	session_keys[key_max_recv_data_length].max = iscsi_init_params.max_data_seg_len;

	/* MaxXmitDataSegmentLength */
	session_keys[key_max_xmit_data_length].local_def = iscsi_init_params.max_data_seg_len;
	session_keys[key_max_xmit_data_length].max = iscsi_init_params.max_data_seg_len;

	/* MaxBurstLength */
	session_keys[key_max_burst_length].local_def = iscsi_init_params.max_data_seg_len;
	session_keys[key_max_burst_length].max = iscsi_init_params.max_data_seg_len;

	/* FirstBurstLength */
	session_keys[key_first_burst_length].local_def =
		min((int)session_keys[key_first_burst_length].local_def,
		    iscsi_init_params.max_data_seg_len);
	session_keys[key_first_burst_length].max = iscsi_init_params.max_data_seg_len;

	return;
}

int main(int argc, char **argv)
{
	int ch, longindex;
	char *config = NULL;
	uid_t uid = 0;
	gid_t gid = 0;
	int err;


	if (pipe(init_report_pipe) == -1) {
		perror("pipe failed");
		exit(-1);
	}

	/*
	 * Otherwise we could die in some later write() during the event_loop()
	 * instead of getting EPIPE!
	 *
	 * The effects of signal(2) in a multithreaded process are unspecified,
	 * so use sigaction(2) instead.
	 */
	struct sigaction act = (struct sigaction) { .sa_handler = SIG_IGN };
	int rc = sigaction(SIGPIPE, &act, NULL);
	assert(rc == 0);

	while ((ch = getopt_long(argc, argv, "c:fd:s:u:g:a:p:vh", long_options, &longindex)) >= 0) {
		switch (ch) {
		case 'c':
			config = optarg;
			break;
		case 'f':
			log_daemon = 0;
			break;
		case 'd':
			log_level = strtol(optarg, NULL, 0);
			break;
		case 'u':
			uid = strtoul(optarg, NULL, 0);
			break;
		case 'g':
			gid = strtoul(optarg, NULL, 0);
			break;
		case 'a':
			server_address = strdup(optarg);
			if (server_address == NULL) {
				perror("strdup failed");
				exit(-1);
			}
			break;
		case 'p':
			server_port = (uint16_t)strtoul(optarg, NULL, 0);
			break;
		case 'v':
			printf("%s version %s\n", program_name, ISCSI_VERSION_STRING);
			exit(0);
			break;
		case 'h':
			usage(0);
			break;
		default:
			usage(1);
			break;
		}
	}

	if ((ctrl_fd = kernel_open()) < 0)
		exit(-1);

	init_max_params();

	if ((nl_fd = nl_open()) < 0) {
		perror("netlink open failed");
		exit(-1);
	};

	err = kernel_attr_add(NULL, ISCSI_ISNS_SERVER_ATTR_NAME,
			S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR, 0);
	if (err != 0)
		exit(err);

	err = kernel_attr_add(NULL, ISCSI_ENABLED_ATTR_NAME,
			S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR, 0);
	if (err != 0)
		exit(err);
	err = kernel_attr_add(NULL, ISCSI_ISNS_ENTITY_ATTR_NAME,
			S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR, 0);
	if (err != 0)
		exit(err);

	if ((ipc_fd = iscsi_adm_request_listen()) < 0) {
		perror("Opening AF_LOCAL socket failed");
		exit(-1);
	}

	log_init();
	if (log_daemon) {
		char buf[64];
		pid_t pid;
		int fd;

		fd = open("/var/run/iscsi-scstd.pid", O_WRONLY|O_CREAT, 0644);
		if (fd < 0) {
			log_error("unable to create pid file");
			exit(1);
		}
		pid = fork();
		if (pid < 0) {
			log_error("starting daemon failed");
			exit(1);
		} else if (pid) {
			int res = -1;

			close(init_report_pipe[1]);
			if (read(init_report_pipe[0], &res, sizeof(res)) < sizeof(res))
				exit(-1);
			else
				exit(res);
		}

		if (chdir("/") < 0) {
			log_error("failed to set working dir to /: %m");
			exit(1);
		}

		if (lockf(fd, F_TLOCK, 0) < 0) {
			log_error("unable to lock pid file");
			exit(1);
		}
		if (ftruncate(fd, 0) < 0) {
			log_error("failed to ftruncate the PID file: %m");
			exit(1);
		}

		sprintf(buf, "%d\n", getpid());
		if (write(fd, buf, strlen(buf)) < strlen(buf)) {
			log_error("failed to write PID to PID file: %m");
			exit(1);
		}

		close(0);
		open("/dev/null", O_RDWR);
		dup2(0, 1);
		dup2(0, 2);
		setsid();
	}

	err = config_load(config);
	if (err != 0)
		exit(1);

	if (gid && setgid(gid) < 0)
		log_error("setgid failed: %s", strerror(errno));

	if (uid && setuid(uid) < 0)
		log_error("setuid failed: %s", strerror(errno));

	event_loop();

	return 0;
}
