Blame usr/netlink.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI Netlink/Linux Interface
Packit Service 646995
 *
Packit Service 646995
 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
Packit Service 646995
 * Copyright (C) 2006 Mike Christie
Packit Service 646995
 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
Packit Service 646995
 * maintained by open-iscsi@googlegroups.com
Packit Service 646995
 *
Packit Service 646995
 * This program is free software; you can redistribute it and/or modify
Packit Service 646995
 * it under the terms of the GNU General Public License as published
Packit Service 646995
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 646995
 * (at your option) any later version.
Packit Service 646995
 *
Packit Service 646995
 * This program is distributed in the hope that it will be useful, but
Packit Service 646995
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 646995
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 646995
 * General Public License for more details.
Packit Service 646995
 *
Packit Service 646995
 * See the file COPYING included with this distribution for more details.
Packit Service 646995
 */
Packit Service 646995
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <stdint.h>
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <time.h>
Packit Service 646995
#include <inttypes.h>
Packit Service 646995
#include <asm/types.h>
Packit Service 646995
#include <sys/socket.h>
Packit Service 646995
#include <sys/types.h>
Packit Service 646995
#include <poll.h>
Packit Service 646995
#include <linux/netlink.h>
Packit Service 646995
Packit Service 646995
#include "types.h"
Packit Service 646995
#include "iscsi_if.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "iscsi_netlink.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "iscsi_timer.h"
Packit Service 646995
Packit Service 646995
static int ctrl_fd;
Packit Service 646995
static struct sockaddr_nl src_addr, dest_addr;
Packit Service 646995
static void *xmitbuf = NULL;
Packit Service 646995
static int xmitlen = 0;
Packit Service 646995
static void *recvbuf = NULL;
Packit Service 646995
static int recvlen = 0;
Packit Service 646995
static void *nlm_sendbuf;
Packit Service 646995
static void *nlm_recvbuf;
Packit Service 646995
static void *pdu_sendbuf;
Packit Service 646995
static void *setparam_buf;
Packit Service 646995
static struct iscsi_ipc_ev_clbk *ipc_ev_clbk;
Packit Service 646995
Packit Service 646995
static int ctldev_handle(void);
Packit Service 646995
Packit Service 646995
#define NLM_BUF_DEFAULT_MAX (NLMSG_SPACE(ISCSI_DEF_MAX_RECV_SEG_LEN +	\
Packit Service 646995
					sizeof(struct iscsi_uevent) +	\
Packit Service 646995
					sizeof(struct iscsi_hdr)))
Packit Service 646995
Packit Service 646995
#define PDU_SENDBUF_DEFAULT_MAX	(ISCSI_DEF_MAX_RECV_SEG_LEN +		\
Packit Service 646995
					sizeof(struct iscsi_uevent) +	\
Packit Service 646995
					sizeof(struct iscsi_hdr))
Packit Service 646995
Packit Service 646995
#define NLM_SETPARAM_DEFAULT_MAX (NI_MAXHOST + 1 + sizeof(struct iscsi_uevent))
Packit Service 646995
Packit Service 646995
struct iscsi_ping_event {
Packit Service 646995
	uint32_t host_no;
Packit Service 646995
	uint32_t pid;
Packit Service 646995
	int32_t status;
Packit Service 646995
	int active;
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_ping_event ping_event;
Packit Service 646995
Packit Service 646995
struct nlattr *iscsi_nla_alloc(uint16_t type, uint16_t len)
Packit Service 646995
{
Packit Service 646995
	struct nlattr *attr;
Packit Service 646995
Packit Service 646995
	attr = calloc(1, ISCSI_NLA_TOTAL_LEN(len));
Packit Service 646995
	if (!attr)
Packit Service 646995
		return NULL; 
Packit Service 646995
Packit Service 646995
	attr->nla_len = ISCSI_NLA_LEN(len);
Packit Service 646995
	attr->nla_type = type;
Packit Service 646995
	return attr;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kread(char *data, int count)
Packit Service 646995
{
Packit Service 646995
	log_debug(7, "in %s %u %u %p %p", __FUNCTION__, recvlen, count,
Packit Service 646995
		  data, recvbuf);
Packit Service 646995
Packit Service 646995
	memcpy(data, recvbuf + recvlen, count);
Packit Service 646995
	recvlen += count;
Packit Service 646995
	return count;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
nl_read(int ctrl_fd, char *data, int size, int flags)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov;
Packit Service 646995
	struct msghdr msg;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	iov.iov_base = data;
Packit Service 646995
	iov.iov_len = size;
Packit Service 646995
Packit Service 646995
	memset(&msg, 0, sizeof(msg));
Packit Service 646995
	msg.msg_name= (void*)&src_addr;
Packit Service 646995
	msg.msg_namelen = sizeof(src_addr);
Packit Service 646995
	msg.msg_iov = &iov;
Packit Service 646995
	msg.msg_iovlen = 1;
Packit Service 646995
Packit Service 646995
	rc = recvmsg(ctrl_fd, &msg, flags);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
nlpayload_read(int ctrl_fd, char *data, int count, int flags)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov;
Packit Service 646995
	struct msghdr msg;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	iov.iov_base = nlm_recvbuf;
Packit Service 646995
	iov.iov_len = NLMSG_SPACE(count);
Packit Service 646995
Packit Service 646995
	if (iov.iov_len > NLM_BUF_DEFAULT_MAX) {
Packit Service 646995
		log_error("Cannot read %zu bytes. nlm_recvbuf too small.",
Packit Service 646995
			  iov.iov_len);
Packit Service 646995
		return -1;
Packit Service 646995
	}
Packit Service 646995
	memset(iov.iov_base, 0, iov.iov_len);
Packit Service 646995
Packit Service 646995
	memset(&msg, 0, sizeof(msg));
Packit Service 646995
	msg.msg_name= (void*)&src_addr;
Packit Service 646995
	msg.msg_namelen = sizeof(src_addr);
Packit Service 646995
	msg.msg_iov = &iov;
Packit Service 646995
	msg.msg_iovlen = 1;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * Netlink recvmsg call path:
Packit Service 646995
	 *
Packit Service 646995
	 *  - transport api callback
Packit Service 646995
	 *  - iscsi_control_conn_error (should succeed)
Packit Service 646995
	 *  - iscsi_unicast_skb (must succeed)
Packit Service 646995
	 *  - netlink_unicast (must succeed)
Packit Service 646995
	 *  - netlink_data_ready (must succeed)
Packit Service 646995
	 *  - netlink_sendskb (must succeed)
Packit Service 646995
	 *  - netlink_recvmsg (must succeed)
Packit Service 646995
	 *  - sock_recvmsg (must succeed)
Packit Service 646995
	 *  - sys_recvmsg (must succeed)
Packit Service 646995
	 *  - sys_socketcall (must succeed)
Packit Service 646995
	 *  - syscall_call (must succeed)
Packit Service 646995
	 *
Packit Service 646995
	 *  Note1: "must succeed" means succeed unless bug in daemon.
Packit Service 646995
	 *        It also means - no sleep and memory allocation on
Packit Service 646995
	 *        the path.
Packit Service 646995
	 *
Packit Service 646995
	 *  Note2: "should succeed" means will succeed in most of cases
Packit Service 646995
	 *        because of mempool preallocation.
Packit Service 646995
	 *
Packit Service 646995
	 *  FIXME: if "Note2" than interface should generate iSCSI error
Packit Service 646995
	 *        level 0 on its own. Interface must always succeed on this.
Packit Service 646995
	 */
Packit Service 646995
	rc = recvmsg(ctrl_fd, &msg, flags);
Packit Service 646995
Packit Service 646995
	if (data)
Packit Service 646995
		memcpy(data, NLMSG_DATA(iov.iov_base), count);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kwritev(enum iscsi_uevent_e type, struct iovec *iovp, int count)
Packit Service 646995
{
Packit Service 646995
	int i, rc;
Packit Service 646995
	struct nlmsghdr *nlh;
Packit Service 646995
	struct msghdr msg;
Packit Service 646995
	int datalen = 0;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	for (i = 0; i < count; i++) {
Packit Service 646995
		datalen += iovp[i].iov_len;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (xmitbuf && type != ISCSI_UEVENT_SEND_PDU) {
Packit Service 646995
		for (i = 0; i < count; i++) {
Packit Service 646995
			memcpy(xmitbuf + xmitlen,
Packit Service 646995
			       iovp[i].iov_base, iovp[i].iov_len);
Packit Service 646995
			xmitlen += iovp[i].iov_len;
Packit Service 646995
		}
Packit Service 646995
		return datalen;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	nlh = nlm_sendbuf;
Packit Service 646995
	memset(nlh, 0, NLMSG_SPACE(0));
Packit Service 646995
Packit Service 646995
	datalen = 0;
Packit Service 646995
	for (i = 1; i < count; i++)
Packit Service 646995
		datalen += iovp[i].iov_len;
Packit Service 646995
Packit Service 646995
	nlh->nlmsg_len = datalen + sizeof(*nlh);
Packit Service 646995
	nlh->nlmsg_pid = getpid();
Packit Service 646995
	nlh->nlmsg_flags = 0;
Packit Service 646995
	nlh->nlmsg_type = type;
Packit Service 646995
Packit Service 646995
	iovp[0].iov_base = (void *)nlh;
Packit Service 646995
	iovp[0].iov_len = sizeof(*nlh);
Packit Service 646995
Packit Service 646995
	memset(&msg, 0, sizeof(msg));
Packit Service 646995
	msg.msg_name= (void*)&dest_addr;
Packit Service 646995
	msg.msg_namelen = sizeof(dest_addr);
Packit Service 646995
	msg.msg_iov = iovp;
Packit Service 646995
	msg.msg_iovlen = count;
Packit Service 646995
Packit Service 646995
	do {
Packit Service 646995
		/*
Packit Service 646995
		 * Netlink down call path:
Packit Service 646995
		 *
Packit Service 646995
		 *  - transport api call
Packit Service 646995
		 *  - iscsi_if_recv_msg (must succeed)
Packit Service 646995
		 *  - iscsi_if_rx (must succeed)
Packit Service 646995
		 *  - netlink_data_ready (must succeed)
Packit Service 646995
		 *  - netlink_sendskb (must succeed)
Packit Service 646995
		 *  - netlink_sendmsg (alloc_skb() might fail)
Packit Service 646995
		 *  - sock_sendmsg (must succeed)
Packit Service 646995
		 *  - sys_sendmsg (must succeed)
Packit Service 646995
		 *  - sys_socketcall (must succeed)
Packit Service 646995
		 *  - syscall_call (must succeed)
Packit Service 646995
		 *
Packit Service 646995
		 *  Note1: "must succeed" means succeed unless bug in daemon.
Packit Service 646995
		 *        It also means - no sleep and memory allocation on
Packit Service 646995
		 *        the path.
Packit Service 646995
		 *
Packit Service 646995
		 *  Note2: netlink_sendmsg() might fail because of OOM. Since
Packit Service 646995
		 *         we are in user-space, we will sleep until we succeed.
Packit Service 646995
		 */
Packit Service 646995
Packit Service 646995
		rc = sendmsg(ctrl_fd, &msg, 0);
Packit Service 646995
		if (rc == -ENOMEM) {
Packit Service 646995
			log_debug(1, "sendmsg: alloc_skb() failed");
Packit Service 646995
			sleep(1);
Packit Service 646995
		} else if (rc < 0) {
Packit Service 646995
			log_error("sendmsg: bug? ctrl_fd %d", ctrl_fd);
Packit Service 646995
			exit(rc);
Packit Service 646995
		}
Packit Service 646995
	} while (rc < 0);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * __kipc_call() should never block. Therefore
Packit Service 646995
 * Netlink's xmit logic is serialized. This means we do not allocate on
Packit Service 646995
 * xmit path. Instead we reuse nlm_sendbuf buffer.
Packit Service 646995
 *
Packit Service 646995
 * Transport must assure non-blocking operations for:
Packit Service 646995
 *
Packit Service 646995
 *	- session_create()
Packit Service 646995
 *	- conn_create()
Packit Service 646995
 *	- conn_bind()
Packit Service 646995
 *	_ set_param()
Packit Service 646995
 *	- conn_start()
Packit Service 646995
 *	- conn_stop()
Packit Service 646995
 *
Packit Service 646995
 * Its OK to block for cleanup for short period of time in operatations for:
Packit Service 646995
 *
Packit Service 646995
 *	- conn_destroy()
Packit Service 646995
 *	- session_destroy()
Packit Service 646995
 *
Packit Service 646995
 * FIXME: interface needs to be extended to allow longer blocking on
Packit Service 646995
 *        cleanup. (Dima)
Packit Service 646995
 */
Packit Service 646995
static int
Packit Service 646995
__kipc_call(struct iovec *iovp, int count)
Packit Service 646995
{
Packit Service 646995
	int rc, iferr;
Packit Service 646995
	struct iscsi_uevent *ev = iovp[1].iov_base;
Packit Service 646995
	enum iscsi_uevent_e type = ev->type;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	rc = kwritev(type, iovp, count);
Packit Service 646995
Packit Service 646995
	do {
Packit Service 646995
		if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
Packit Service 646995
					 sizeof(*ev), MSG_PEEK)) < 0) {
Packit Service 646995
			return rc;
Packit Service 646995
		}
Packit Service 646995
		if (ev->type != type) {
Packit Service 646995
			log_debug(1, "expecting event %d, got %d, handling...",
Packit Service 646995
				  type, ev->type);
Packit Service 646995
			if (ev->type == ISCSI_KEVENT_IF_ERROR) {
Packit Service 646995
				if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
Packit Service 646995
							 sizeof(*ev), 0)) < 0) {
Packit Service 646995
					return rc;
Packit Service 646995
				}
Packit Service 646995
				/*
Packit Service 646995
				 * iferror is u32, but the kernel returns
Packit Service 646995
				 * negative errno values for errors.
Packit Service 646995
				 */
Packit Service 646995
				iferr = ev->iferror;
Packit Service 646995
Packit Service 646995
				if (iferr == -ENOSYS)
Packit Service 646995
					/* not fatal so let caller handle log */
Packit Service 646995
					log_debug(1, "Received iferror %d: %s.",
Packit Service 646995
						  iferr, strerror(-iferr));
Packit Service 646995
				else if (iferr < 0)
Packit Service 646995
					log_error("Received iferror %d: %s.",
Packit Service 646995
						   iferr, strerror(-iferr));
Packit Service 646995
				else
Packit Service 646995
					log_error("Received iferror %d.",
Packit Service 646995
						   iferr);
Packit Service 646995
				return ev->iferror;
Packit Service 646995
			}
Packit Service 646995
			/*
Packit Service 646995
			 * receive and queue async. event which as of
Packit Service 646995
			 * today could be:
Packit Service 646995
			 *	- CONN_ERROR
Packit Service 646995
			 *	- RECV_PDU
Packit Service 646995
			 */
Packit Service 646995
			ctldev_handle();
Packit Service 646995
		} else if (ev->type == ISCSI_UEVENT_GET_STATS) {
Packit Service 646995
			/* kget_stats() will read */
Packit Service 646995
			return 0;
Packit Service 646995
		} else if (ev->type == ISCSI_UEVENT_GET_CHAP) {
Packit Service 646995
			/* kget_chap() will read */
Packit Service 646995
			return 0;
Packit Service 646995
		} else if (ev->type == ISCSI_UEVENT_GET_HOST_STATS) {
Packit Service 646995
			/* kget_host_stats() will read */
Packit Service 646995
			return 0;
Packit Service 646995
Packit Service 646995
		} else {
Packit Service 646995
			if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
Packit Service 646995
						 sizeof(*ev), 0)) < 0) {
Packit Service 646995
				return rc;
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	} while (ev->type != type);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
ksendtargets(uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr)
Packit Service 646995
{
Packit Service 646995
	int rc, addrlen;
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->type = ISCSI_UEVENT_TGT_DSCVR;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.tgt_dscvr.type = ISCSI_TGT_DSCVR_SEND_TARGETS;
Packit Service 646995
	ev->u.tgt_dscvr.host_no = host_no;
Packit Service 646995
Packit Service 646995
	if (addr->sa_family == PF_INET)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in);
Packit Service 646995
	else if (addr->sa_family == PF_INET6)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in6);
Packit Service 646995
	else {
Packit Service 646995
		log_error("%s unknown addr family %d",
Packit Service 646995
			  __FUNCTION__, addr->sa_family);
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
	memcpy(setparam_buf + sizeof(*ev), addr, addrlen);
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + addrlen;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("sendtargets failed rc%d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kcreate_session(uint64_t transport_handle, uint64_t ep_handle,
Packit Service 646995
		uint32_t initial_cmdsn, uint16_t cmds_max, uint16_t qdepth,
Packit Service 646995
		uint32_t *out_sid, uint32_t *hostno)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	if (ep_handle == 0) {
Packit Service 646995
		ev.type = ISCSI_UEVENT_CREATE_SESSION;
Packit Service 646995
		ev.transport_handle = transport_handle;
Packit Service 646995
		ev.u.c_session.initial_cmdsn = initial_cmdsn;
Packit Service 646995
		ev.u.c_session.cmds_max = cmds_max;
Packit Service 646995
		ev.u.c_session.queue_depth = qdepth;
Packit Service 646995
	} else {
Packit Service 646995
		ev.type = ISCSI_UEVENT_CREATE_BOUND_SESSION;
Packit Service 646995
		ev.transport_handle = transport_handle;
Packit Service 646995
		ev.u.c_bound_session.initial_cmdsn = initial_cmdsn;
Packit Service 646995
		ev.u.c_bound_session.cmds_max = cmds_max;
Packit Service 646995
		ev.u.c_bound_session.queue_depth = qdepth;
Packit Service 646995
		ev.u.c_bound_session.ep_handle = ep_handle;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	*hostno = ev.r.c_session_ret.host_no;
Packit Service 646995
	*out_sid = ev.r.c_session_ret.sid;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kdestroy_session(uint64_t transport_handle, uint32_t sid)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_DESTROY_SESSION;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.d_session.sid = sid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kunbind_session(uint64_t transport_handle, uint32_t sid)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_UNBIND_SESSION;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.d_session.sid = sid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kcreate_conn(uint64_t transport_handle, uint32_t sid,
Packit Service 646995
	    uint32_t cid, uint32_t *out_cid)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_CREATE_CONN;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.c_conn.cid = cid;
Packit Service 646995
	ev.u.c_conn.sid = sid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_debug(7, "returned %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((int)ev.r.c_conn_ret.cid == -1)
Packit Service 646995
		return -EIO;
Packit Service 646995
Packit Service 646995
	*out_cid = ev.r.c_conn_ret.cid;
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kdestroy_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_DESTROY_CONN;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.d_conn.sid = sid;
Packit Service 646995
	ev.u.d_conn.cid = cid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kbind_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
Packit Service 646995
	  uint64_t transport_eph, int is_leading, int *retcode)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_BIND_CONN;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.b_conn.sid = sid;
Packit Service 646995
	ev.u.b_conn.cid = cid;
Packit Service 646995
	ev.u.b_conn.transport_eph = transport_eph;
Packit Service 646995
	ev.u.b_conn.is_leading = is_leading;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	*retcode = ev.r.retcode;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void
Packit Service 646995
ksend_pdu_begin(uint64_t transport_handle, uint32_t sid, uint32_t cid,
Packit Service 646995
			int hdr_size, int data_size)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	int total_xmitlen = sizeof(*ev) + hdr_size + data_size;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (xmitbuf) {
Packit Service 646995
		log_error("send's begin state machine bug?");
Packit Service 646995
		exit(-EIO);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (total_xmitlen > (int)PDU_SENDBUF_DEFAULT_MAX) {
Packit Service 646995
		log_error("BUG: Cannot send %d bytes.", total_xmitlen);
Packit Service 646995
		exit(-EINVAL);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	xmitbuf = pdu_sendbuf;
Packit Service 646995
	memset(xmitbuf, 0, total_xmitlen);
Packit Service 646995
	xmitlen = sizeof(*ev);
Packit Service 646995
	ev = xmitbuf;
Packit Service 646995
	memset(ev, 0, sizeof(*ev));
Packit Service 646995
	ev->type = ISCSI_UEVENT_SEND_PDU;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.send_pdu.sid = sid;
Packit Service 646995
	ev->u.send_pdu.cid = cid;
Packit Service 646995
	ev->u.send_pdu.hdr_size = hdr_size;
Packit Service 646995
	ev->u.send_pdu.data_size = data_size;
Packit Service 646995
Packit Service 646995
	log_debug(3, "send PDU began for hdr %d bytes and data %d bytes",
Packit Service 646995
		hdr_size, data_size);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
ksend_pdu_end(__attribute__((unused))uint64_t transport_handle,
Packit Service 646995
	      uint32_t sid, uint32_t cid, int *retcode)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (!xmitbuf) {
Packit Service 646995
		log_error("send's end state machine bug?");
Packit Service 646995
		exit(-EIO);
Packit Service 646995
	}
Packit Service 646995
	ev = xmitbuf;
Packit Service 646995
	if (ev->u.send_pdu.sid != sid || ev->u.send_pdu.cid != cid) {
Packit Service 646995
		log_error("send's end state machine corruption?");
Packit Service 646995
		exit(-EIO);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = xmitbuf;
Packit Service 646995
	iov[1].iov_len = xmitlen;
Packit Service 646995
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		goto err;
Packit Service 646995
	if (ev->r.retcode) {
Packit Service 646995
		*retcode = ev->r.retcode;
Packit Service 646995
		goto err;
Packit Service 646995
	}
Packit Service 646995
	if (ev->type != ISCSI_UEVENT_SEND_PDU) {
Packit Service 646995
		log_error("bad event: bug on send_pdu_end?");
Packit Service 646995
		exit(-EIO);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_debug(3, "send PDU finished for conn %d:%d",
Packit Service 646995
		  sid, cid);
Packit Service 646995
Packit Service 646995
	xmitbuf = NULL;
Packit Service 646995
	return 0;
Packit Service 646995
Packit Service 646995
err:
Packit Service 646995
	xmitbuf = NULL;
Packit Service 646995
	xmitlen = 0;
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kset_host_param(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		enum iscsi_host_param param, void *value, int type)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	char *param_str;
Packit Service 646995
	int rc, len;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->type = ISCSI_UEVENT_SET_HOST_PARAM;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.set_host_param.host_no = host_no;
Packit Service 646995
	ev->u.set_host_param.param = param;
Packit Service 646995
Packit Service 646995
	param_str = setparam_buf + sizeof(*ev);
Packit Service 646995
	switch (type) {
Packit Service 646995
	case ISCSI_INT:
Packit Service 646995
		sprintf(param_str, "%d", *((int *)value));
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_STRING:
Packit Service 646995
		if (!strlen(value))
Packit Service 646995
			return 0;
Packit Service 646995
		sprintf(param_str, "%s", (char *)value);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("invalid type %d", type);
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
	ev->u.set_host_param.len = len = strlen(param_str) + 1;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + len;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kset_param(uint64_t transport_handle, uint32_t sid, uint32_t cid,
Packit Service 646995
	   enum iscsi_param param, void *value, int type)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	char *param_str;
Packit Service 646995
	int rc, len;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->type = ISCSI_UEVENT_SET_PARAM;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.set_param.sid = sid;
Packit Service 646995
	ev->u.set_param.cid = cid;
Packit Service 646995
	ev->u.set_param.param = param;
Packit Service 646995
Packit Service 646995
	param_str = setparam_buf + sizeof(*ev);
Packit Service 646995
	switch (type) {
Packit Service 646995
	case ISCSI_INT:
Packit Service 646995
		sprintf(param_str, "%d", *((int *)value));
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_UINT:
Packit Service 646995
		sprintf(param_str, "%u", *((unsigned int *)value));
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_STRING:
Packit Service 646995
		if (!strlen(value))
Packit Service 646995
			return 0;
Packit Service 646995
		sprintf(param_str, "%s", (char *)value);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("invalid type %d", type);
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
	ev->u.set_param.len = len = strlen(param_str) + 1;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + len;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kstop_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid, int flag)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_STOP_CONN;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.stop_conn.sid = sid;
Packit Service 646995
	ev.u.stop_conn.cid = cid;
Packit Service 646995
	ev.u.stop_conn.flag = flag;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kstart_conn(uint64_t transport_handle, uint32_t sid, uint32_t cid,
Packit Service 646995
	    int *retcode)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_START_CONN;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.start_conn.sid = sid;
Packit Service 646995
	ev.u.start_conn.cid = cid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	*retcode = ev.r.retcode;
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
krecv_pdu_begin(struct iscsi_conn *conn)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (recvbuf) {
Packit Service 646995
		log_error("recv's begin state machine bug?");
Packit Service 646995
		return -EIO;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!conn->recv_context) {
Packit Service 646995
		rc = ipc->ctldev_handle();
Packit Service 646995
		if (rc == -ENXIO)
Packit Service 646995
			/* event for some other conn */
Packit Service 646995
			return -EAGAIN;
Packit Service 646995
		else if (rc < 0)
Packit Service 646995
			/* fatal handling error or conn error */
Packit Service 646995
			return rc;
Packit Service 646995
		/*
Packit Service 646995
		 * Session create/destroy event for another conn
Packit Service 646995
		 */
Packit Service 646995
		if (!conn->recv_context)
Packit Service 646995
			return -EAGAIN;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	recvbuf = conn->recv_context->data + sizeof(struct iscsi_uevent);
Packit Service 646995
	recvlen = 0;
Packit Service 646995
Packit Service 646995
	log_debug(3, "recv PDU began, pdu handle %p", recvbuf);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
krecv_pdu_end(struct iscsi_conn *conn)
Packit Service 646995
{
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (!recvbuf) {
Packit Service 646995
		log_error("recv's end state machine bug?");
Packit Service 646995
		return -EIO;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_debug(3, "recv PDU finished for pdu handle 0x%p",
Packit Service 646995
		  recvbuf);
Packit Service 646995
Packit Service 646995
	ipc_ev_clbk->put_ev_context(conn->recv_context);
Packit Service 646995
	conn->recv_context = NULL;
Packit Service 646995
	recvbuf = NULL;
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int
Packit Service 646995
ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
Packit Service 646995
{
Packit Service 646995
	int rc, addrlen;
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	struct sockaddr *dst_addr = (struct sockaddr *)&conn->saddr;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->transport_handle = conn->session->t->handle;
Packit Service 646995
Packit Service 646995
	if (conn->bind_ep) {
Packit Service 646995
		ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST;
Packit Service 646995
		ev->u.ep_connect_through_host.non_blocking = non_blocking;
Packit Service 646995
		ev->u.ep_connect_through_host.host_no = conn->session->hostno;
Packit Service 646995
	} else {
Packit Service 646995
		ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
Packit Service 646995
		ev->u.ep_connect.non_blocking = non_blocking;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (dst_addr->sa_family == PF_INET)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in);
Packit Service 646995
	else if (dst_addr->sa_family == PF_INET6)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in6);
Packit Service 646995
	else {
Packit Service 646995
		log_error("%s unknown addr family %d",
Packit Service 646995
			 __FUNCTION__, dst_addr->sa_family);
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
	memcpy(setparam_buf + sizeof(*ev), dst_addr, addrlen);
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + addrlen;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	if (!ev->r.ep_connect_ret.handle)
Packit Service 646995
		return -EIO;
Packit Service 646995
Packit Service 646995
	conn->transport_ep_handle = ev->r.ep_connect_ret.handle;
Packit Service 646995
Packit Service 646995
	log_debug(6, "%s got handle %llx",
Packit Service 646995
		__FUNCTION__, (unsigned long long)conn->transport_ep_handle);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int
Packit Service 646995
ktransport_ep_poll(iscsi_conn_t *conn, int timeout_ms)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_TRANSPORT_EP_POLL;
Packit Service 646995
	ev.transport_handle = conn->session->t->handle;
Packit Service 646995
	ev.u.ep_poll.ep_handle  = conn->transport_ep_handle;
Packit Service 646995
	ev.u.ep_poll.timeout_ms = timeout_ms;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return ev.r.retcode;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
void
Packit Service 646995
ktransport_ep_disconnect(iscsi_conn_t *conn)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (conn->transport_ep_handle == (uint64_t)-1)
Packit Service 646995
		return;
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT;
Packit Service 646995
	ev.transport_handle = conn->session->t->handle;
Packit Service 646995
	ev.u.ep_disconnect.ep_handle = conn->transport_ep_handle;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("connection %d:%d transport disconnect failed for "
Packit Service 646995
			  "ep %" PRIu64 " with error %d.", conn->session->id,
Packit Service 646995
			  conn->id, conn->transport_ep_handle, rc);
Packit Service 646995
	} else
Packit Service 646995
		conn->transport_ep_handle = -1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kget_stats(uint64_t transport_handle, uint32_t sid, uint32_t cid,
Packit Service 646995
	   char *statsbuf, int statsbuf_max)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	int ev_size;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Packit Service 646995
	struct nlmsghdr *nlh;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_GET_STATS;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.get_stats.sid = sid;
Packit Service 646995
	ev.u.get_stats.cid = cid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	if ((rc = nl_read(ctrl_fd, nlm_ev,
Packit Service 646995
		NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
Packit Service 646995
		log_error("can not read nlm_ev, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
	nlh = (struct nlmsghdr *)nlm_ev;
Packit Service 646995
	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Packit Service 646995
Packit Service 646995
	log_debug(6, "message real length is %d bytes", nlh->nlmsg_len);
Packit Service 646995
Packit Service 646995
	if (ev_size > statsbuf_max) {
Packit Service 646995
		log_error("destanation buffer for statistics is "
Packit Service 646995
			"not big enough to fit %d bytes", statsbuf_max);
Packit Service 646995
		ev_size = statsbuf_max;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((rc = nlpayload_read(ctrl_fd, (void*)statsbuf, ev_size, 0)) < 0) {
Packit Service 646995
		log_error("can not read from NL socket, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kset_net_config(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		struct iovec *iovs, uint32_t param_count)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc, ev_len;
Packit Service 646995
	struct iovec *iov = iovs + 1;
Packit Service 646995
Packit Service 646995
	log_debug(8, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	ev_len = sizeof(ev);
Packit Service 646995
	ev.type = ISCSI_UEVENT_SET_IFACE_PARAMS;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.set_iface_params.host_no = host_no;
Packit Service 646995
	/* first two iovs for nlmsg hdr and ev */
Packit Service 646995
	ev.u.set_iface_params.count = param_count - 2;
Packit Service 646995
Packit Service 646995
	iov->iov_base = &ev;
Packit Service 646995
	iov->iov_len = ev_len;
Packit Service 646995
	rc = __kipc_call(iovs, param_count);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int krecv_conn_state(struct iscsi_conn *conn, uint32_t *state)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	rc = ipc->ctldev_handle();
Packit Service 646995
	if (rc == -ENXIO) {
Packit Service 646995
		/* event for some other conn */
Packit Service 646995
		rc = -EAGAIN;
Packit Service 646995
		goto exit;
Packit Service 646995
	} else if (rc < 0)
Packit Service 646995
		/* fatal handling error or conn error */
Packit Service 646995
		goto exit;
Packit Service 646995
Packit Service 646995
        /* unexpected event without a receive context */
Packit Service 646995
        if (!conn->recv_context)
Packit Service 646995
                return -EAGAIN;
Packit Service 646995
Packit Service 646995
	*state = *(enum iscsi_conn_state *)conn->recv_context->data;
Packit Service 646995
Packit Service 646995
	ipc_ev_clbk->put_ev_context(conn->recv_context);
Packit Service 646995
	conn->recv_context = NULL;
Packit Service 646995
Packit Service 646995
exit:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
Packit Service 646995
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
ksend_ping(uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr,
Packit Service 646995
	   uint32_t iface_num, uint32_t iface_type, uint32_t pid, uint32_t size)
Packit Service 646995
{
Packit Service 646995
	int rc, addrlen;
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(8, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->type = ISCSI_UEVENT_PING;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.iscsi_ping.host_no = host_no;
Packit Service 646995
	ev->u.iscsi_ping.iface_num = iface_num;
Packit Service 646995
	ev->u.iscsi_ping.iface_type = iface_type;
Packit Service 646995
	ev->u.iscsi_ping.payload_size = size;
Packit Service 646995
	ev->u.iscsi_ping.pid = pid;
Packit Service 646995
Packit Service 646995
	if (addr->sa_family == PF_INET)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in);
Packit Service 646995
	else if (addr->sa_family == PF_INET6)
Packit Service 646995
		addrlen = sizeof(struct sockaddr_in6);
Packit Service 646995
	else {
Packit Service 646995
		log_error("%s unknown addr family %d",
Packit Service 646995
			  __FUNCTION__, addr->sa_family);
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
	memcpy(setparam_buf + sizeof(*ev), addr, addrlen);
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + addrlen;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int kexec_ping(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		      struct sockaddr *addr, uint32_t iface_num,
Packit Service 646995
		      uint32_t iface_type, uint32_t size, uint32_t *status)
Packit Service 646995
{
Packit Service 646995
	struct pollfd pfd;
Packit Service 646995
	struct timeval ping_timer;
Packit Service 646995
	int timeout, fd, rc;
Packit Service 646995
	uint32_t pid;
Packit Service 646995
Packit Service 646995
	*status = 0;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Could not open netlink socket.");
Packit Service 646995
		return ISCSI_ERR;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* prepare to poll */
Packit Service 646995
	memset(&pfd, 0, sizeof(pfd));
Packit Service 646995
	pfd.fd = fd;
Packit Service 646995
	pfd.events = POLLIN | POLLPRI;
Packit Service 646995
Packit Service 646995
	/* get unique ping id */
Packit Service 646995
	pid = rand();
Packit Service 646995
Packit Service 646995
	rc = ksend_ping(transport_handle, host_no, addr, iface_num,
Packit Service 646995
			iface_type, pid, size);
Packit Service 646995
	if (rc != 0) {
Packit Service 646995
		switch (rc) {
Packit Service 646995
		case -ENOSYS:
Packit Service 646995
			rc = ISCSI_ERR_OP_NOT_SUPP;
Packit Service 646995
			break;
Packit Service 646995
		case -EINVAL:
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		default:
Packit Service 646995
			rc = ISCSI_ERR;
Packit Service 646995
		}
Packit Service 646995
		goto close_nl;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	ping_event.host_no = -1;
Packit Service 646995
	ping_event.pid = -1;
Packit Service 646995
	ping_event.status = -1;
Packit Service 646995
	ping_event.active = -1;
Packit Service 646995
Packit Service 646995
	iscsi_timer_set(&ping_timer, 30);
Packit Service 646995
Packit Service 646995
	timeout = iscsi_timer_msecs_until(&ping_timer);
Packit Service 646995
Packit Service 646995
	while (1) {
Packit Service 646995
		pfd.revents = 0;
Packit Service 646995
		rc = poll(&pfd, 1, timeout);
Packit Service 646995
Packit Service 646995
		if (iscsi_timer_expired(&ping_timer)) {
Packit Service 646995
			rc = ISCSI_ERR_TRANS_TIMEOUT;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (rc > 0) {
Packit Service 646995
			if (pfd.revents & (POLLIN | POLLPRI)) {
Packit Service 646995
				timeout = iscsi_timer_msecs_until(&ping_timer);
Packit Service 646995
				rc = ipc->ctldev_handle();
Packit Service 646995
Packit Service 646995
				if (ping_event.active != 1)
Packit Service 646995
					continue;
Packit Service 646995
Packit Service 646995
				if (pid != ping_event.pid)
Packit Service 646995
					continue;
Packit Service 646995
Packit Service 646995
				rc = 0;
Packit Service 646995
				*status = ping_event.status;
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			if (pfd.revents & POLLHUP) {
Packit Service 646995
				rc = ISCSI_ERR_TRANS;
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			if (pfd.revents & POLLNVAL) {
Packit Service 646995
				rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			if (pfd.revents & POLLERR) {
Packit Service 646995
				rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
		} else if (rc < 0) {
Packit Service 646995
			rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
close_nl:
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int kget_chap(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		     uint16_t chap_tbl_idx, uint32_t num_entries,
Packit Service 646995
		     char *chap_buf, uint32_t *valid_chap_entries)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	int ev_size;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Packit Service 646995
	struct nlmsghdr *nlh;
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_GET_CHAP;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.get_chap.host_no = host_no;
Packit Service 646995
	ev.u.get_chap.chap_tbl_idx = chap_tbl_idx;
Packit Service 646995
	ev.u.get_chap.num_entries = num_entries;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	if ((rc = nl_read(ctrl_fd, nlm_ev,
Packit Service 646995
			  NLMSG_SPACE(sizeof(struct iscsi_uevent)),
Packit Service 646995
			  MSG_PEEK)) < 0) {
Packit Service 646995
		log_error("can not read nlm_ev, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	nlh = (struct nlmsghdr *)nlm_ev;
Packit Service 646995
	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Packit Service 646995
Packit Service 646995
	if ((rc = nlpayload_read(ctrl_fd, (void *)chap_buf, ev_size, 0)) < 0) {
Packit Service 646995
		log_error("can not read from NL socket, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	*valid_chap_entries = ev.u.get_chap.num_entries;
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int kset_chap(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
			struct iovec *iovs, uint32_t param_count)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec *iov = iovs + 1;
Packit Service 646995
Packit Service 646995
	log_debug(8, "in %s", __func__);
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_SET_CHAP;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.set_path.host_no = host_no;
Packit Service 646995
Packit Service 646995
	iov->iov_base = &ev;
Packit Service 646995
	iov->iov_len = sizeof(ev);
Packit Service 646995
Packit Service 646995
	rc = __kipc_call(iovs, param_count);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int kdelete_chap(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
			uint16_t chap_tbl_idx)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_DELETE_CHAP;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.delete_chap.host_no = host_no;
Packit Service 646995
	ev.u.delete_chap.chap_tbl_idx = chap_tbl_idx;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kset_flashnode_params(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		      uint32_t flashnode_idx, struct iovec *iovs,
Packit Service 646995
		      uint32_t param_count)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc, ev_len;
Packit Service 646995
	struct iovec *iov = iovs + 1;
Packit Service 646995
Packit Service 646995
	log_debug(8, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	ev_len = sizeof(ev);
Packit Service 646995
	ev.type = ISCSI_UEVENT_SET_FLASHNODE_PARAMS;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.set_flashnode.host_no = host_no;
Packit Service 646995
	ev.u.set_flashnode.flashnode_idx = flashnode_idx;
Packit Service 646995
	/* first two iovs for nlmsg hdr and ev */
Packit Service 646995
	ev.u.set_flashnode.count = param_count - 2;
Packit Service 646995
Packit Service 646995
	iov->iov_base = &ev;
Packit Service 646995
	iov->iov_len = ev_len;
Packit Service 646995
	rc = __kipc_call(iovs, param_count);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
knew_flashnode(uint64_t transport_handle, uint32_t host_no, void *value,
Packit Service 646995
	       uint32_t *flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	char *param_str;
Packit Service 646995
	int rc, len;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	ev = (struct iscsi_uevent *)setparam_buf;
Packit Service 646995
	ev->type = ISCSI_UEVENT_NEW_FLASHNODE;
Packit Service 646995
	ev->transport_handle = transport_handle;
Packit Service 646995
	ev->u.new_flashnode.host_no = host_no;
Packit Service 646995
Packit Service 646995
	param_str = setparam_buf + sizeof(*ev);
Packit Service 646995
	if (!strlen(value))
Packit Service 646995
		return 0;
Packit Service 646995
	sprintf(param_str, "%s", (char *)value);
Packit Service 646995
	len = strlen(param_str) + 1;
Packit Service 646995
	ev->u.new_flashnode.len = len;
Packit Service 646995
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = ev;
Packit Service 646995
	iov[1].iov_len = sizeof(*ev) + len;
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	*flashnode_idx = ev->r.new_flashnode_ret.flashnode_idx;
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
kdel_flashnode(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
	       uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
	ev.type = ISCSI_UEVENT_DEL_FLASHNODE;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.del_flashnode.host_no = host_no;
Packit Service 646995
	ev.u.del_flashnode.flashnode_idx = flashnode_idx;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
klogin_flashnode(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		 uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
	ev.type = ISCSI_UEVENT_LOGIN_FLASHNODE;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.login_flashnode.host_no = host_no;
Packit Service 646995
	ev.u.login_flashnode.flashnode_idx = flashnode_idx;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
klogout_flashnode(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		  uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
	ev.type = ISCSI_UEVENT_LOGOUT_FLASHNODE;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.logout_flashnode.host_no = host_no;
Packit Service 646995
	ev.u.logout_flashnode.flashnode_idx = flashnode_idx;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
klogout_flashnode_sid(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		      uint32_t sid)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	int rc;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
	ev.type = ISCSI_UEVENT_LOGOUT_FLASHNODE_SID;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.logout_flashnode_sid.host_no = host_no;
Packit Service 646995
	ev.u.logout_flashnode_sid.sid = sid;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int kget_host_stats(uint64_t transport_handle, uint32_t host_no,
Packit Service 646995
		     char *host_stats)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	int ev_size;
Packit Service 646995
	struct iscsi_uevent ev;
Packit Service 646995
	struct iovec iov[2];
Packit Service 646995
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Packit Service 646995
	struct nlmsghdr *nlh;
Packit Service 646995
Packit Service 646995
	memset(&ev, 0, sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	ev.type = ISCSI_UEVENT_GET_HOST_STATS;
Packit Service 646995
	ev.transport_handle = transport_handle;
Packit Service 646995
	ev.u.get_host_stats.host_no = host_no;
Packit Service 646995
Packit Service 646995
	iov[1].iov_base = &ev;
Packit Service 646995
	iov[1].iov_len = sizeof(ev);
Packit Service 646995
	rc = __kipc_call(iov, 2);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	if ((rc = nl_read(ctrl_fd, nlm_ev,
Packit Service 646995
			  NLMSG_SPACE(sizeof(struct iscsi_uevent)),
Packit Service 646995
			  MSG_PEEK)) < 0) {
Packit Service 646995
		log_error("can not read nlm_ev, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	nlh = (struct nlmsghdr *)nlm_ev;
Packit Service 646995
	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Packit Service 646995
Packit Service 646995
	if ((rc = nlpayload_read(ctrl_fd, (void *)host_stats,
Packit Service 646995
				 ev_size, 0)) < 0) {
Packit Service 646995
		log_error("can not read from NL socket, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
Packit Service 646995
static void drop_data(struct nlmsghdr *nlh)
Packit Service 646995
{
Packit Service 646995
	int ev_size;
Packit Service 646995
Packit Service 646995
	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Packit Service 646995
	nlpayload_read(ctrl_fd, NULL, ev_size, 0);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int ctldev_handle(void)
Packit Service 646995
{
Packit Service 646995
	int rc, ev_size;
Packit Service 646995
	struct iscsi_uevent *ev;
Packit Service 646995
	iscsi_session_t *session = NULL;
Packit Service 646995
	iscsi_conn_t *conn = NULL;
Packit Service 646995
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Packit Service 646995
	struct nlmsghdr *nlh;
Packit Service 646995
	struct iscsi_ev_context *ev_context;
Packit Service 646995
	uint32_t sid = 0, cid = 0;
Packit Service 646995
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if ((rc = nl_read(ctrl_fd, nlm_ev,
Packit Service 646995
		NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
Packit Service 646995
		log_error("can not read nlm_ev, error %d", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
	nlh = (struct nlmsghdr *)nlm_ev;
Packit Service 646995
	ev = (struct iscsi_uevent *)NLMSG_DATA(nlm_ev);
Packit Service 646995
Packit Service 646995
	log_debug(7, "%s got event type %u", __FUNCTION__, ev->type);
Packit Service 646995
	/* drivers like qla4xxx can be inserted after iscsid is started */
Packit Service 646995
	switch (ev->type) {
Packit Service 646995
	case ISCSI_KEVENT_CREATE_SESSION:
Packit Service 646995
	/* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
Packit Service 646995
	case ISCSI_UEVENT_CREATE_SESSION:
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		if (!ipc_ev_clbk)
Packit Service 646995
			return 0;
Packit Service 646995
Packit Service 646995
		if (ipc_ev_clbk->create_session)
Packit Service 646995
			ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
Packit Service 646995
						    ev->r.c_session_ret.sid);
Packit Service 646995
		return 0;
Packit Service 646995
	case ISCSI_KEVENT_DESTROY_SESSION:
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		if (!ipc_ev_clbk)
Packit Service 646995
			return 0;
Packit Service 646995
Packit Service 646995
		if (ipc_ev_clbk->destroy_session)
Packit Service 646995
			ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
Packit Service 646995
						     ev->r.d_session.sid);
Packit Service 646995
		return 0;
Packit Service 646995
	case ISCSI_KEVENT_RECV_PDU:
Packit Service 646995
		sid = ev->r.recv_req.sid;
Packit Service 646995
		cid = ev->r.recv_req.cid;
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_CONN_ERROR:
Packit Service 646995
		sid = ev->r.connerror.sid;
Packit Service 646995
		cid = ev->r.connerror.cid;
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_CONN_LOGIN_STATE:
Packit Service 646995
		sid = ev->r.conn_login.sid;
Packit Service 646995
		cid = ev->r.conn_login.cid;
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_UNBIND_SESSION:
Packit Service 646995
		sid = ev->r.unbind_session.sid;
Packit Service 646995
		/* session wide event so cid is 0 */
Packit Service 646995
		cid = 0;
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_HOST_EVENT:
Packit Service 646995
		switch (ev->r.host_event.code) {
Packit Service 646995
		case ISCSI_EVENT_LINKUP:
Packit Service 646995
			log_warning("Host%u: Link Up.",
Packit Service 646995
				    ev->r.host_event.host_no);
Packit Service 646995
			break;
Packit Service 646995
		case ISCSI_EVENT_LINKDOWN:
Packit Service 646995
			log_warning("Host%u: Link Down.",
Packit Service 646995
				    ev->r.host_event.host_no);
Packit Service 646995
			break;
Packit Service 646995
		default:
Packit Service 646995
			log_debug(7, "Host%u: Unknown host event: %u.",
Packit Service 646995
				  ev->r.host_event.host_no,
Packit Service 646995
				  ev->r.host_event.code);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		return 0;
Packit Service 646995
	case ISCSI_KEVENT_PING_COMP:
Packit Service 646995
		ping_event.host_no = ev->r.ping_comp.host_no;
Packit Service 646995
		ping_event.pid = ev->r.ping_comp.pid;
Packit Service 646995
		ping_event.status = ev->r.ping_comp.status;
Packit Service 646995
		ping_event.active = 1;
Packit Service 646995
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		return 0;
Packit Service 646995
	default:
Packit Service 646995
		if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
Packit Service 646995
		    (ev->type > ISCSI_KEVENT_MAX))
Packit Service 646995
			log_error("Unknown kernel event %d. You may want to "
Packit Service 646995
				  " upgrade your iscsi tools.", ev->type);
Packit Service 646995
		else
Packit Service 646995
			/*
Packit Service 646995
			 * If another app is using the interface we might
Packit Service 646995
			 * see their
Packit Service 646995
			 * stuff. Just drop it.
Packit Service 646995
			 */
Packit Service 646995
			log_debug(7, "Got unknown event %d. Dropping.",
Packit Service 646995
				  ev->type);
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		return 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* verify connection */
Packit Service 646995
	session = session_find_by_sid(sid);
Packit Service 646995
	if (!session) {
Packit Service 646995
		/*
Packit Service 646995
		 * this can happen normally when other apps are using the
Packit Service 646995
		 * nl interface.
Packit Service 646995
		 */
Packit Service 646995
		log_debug(1, "Could not verify connection %d:%d. Dropping "
Packit Service 646995
			   "event.", sid, cid);
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		return -ENXIO;
Packit Service 646995
	}
Packit Service 646995
	conn = &session->conn[0];
Packit Service 646995
Packit Service 646995
	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Packit Service 646995
Packit Service 646995
	ev_context = ipc_ev_clbk->get_ev_context(conn, ev_size);
Packit Service 646995
	if (!ev_context) {
Packit Service 646995
		log_error("Can not allocate memory for receive context.");
Packit Service 646995
		drop_data(nlh);
Packit Service 646995
		return -ENOMEM;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_debug(6, "message real length is %d bytes, recv_handle %p",
Packit Service 646995
		nlh->nlmsg_len, ev_context->data);
Packit Service 646995
Packit Service 646995
	if ((rc = nlpayload_read(ctrl_fd, ev_context->data,
Packit Service 646995
				ev_size, 0)) < 0) {
Packit Service 646995
		ipc_ev_clbk->put_ev_context(ev_context);
Packit Service 646995
		log_error("can not read from NL socket, error %d", rc);
Packit Service 646995
		/* retry later */
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * we sched these events because the handlers could call back
Packit Service 646995
	 * into ctldev_handle
Packit Service 646995
	 */
Packit Service 646995
	switch (ev->type) {
Packit Service 646995
	case ISCSI_KEVENT_RECV_PDU:
Packit Service 646995
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
Packit Service 646995
						   EV_CONN_RECV_PDU);
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_CONN_ERROR:
Packit Service 646995
		memcpy(ev_context->data, &ev->r.connerror.error,
Packit Service 646995
			sizeof(ev->r.connerror.error));
Packit Service 646995
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
Packit Service 646995
						   EV_CONN_ERROR);
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_CONN_LOGIN_STATE:
Packit Service 646995
		memcpy(ev_context->data, &ev->r.conn_login.state,
Packit Service 646995
			sizeof(ev->r.conn_login.state));
Packit Service 646995
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
Packit Service 646995
						   EV_CONN_LOGIN);
Packit Service 646995
		break;
Packit Service 646995
	case ISCSI_KEVENT_UNBIND_SESSION:
Packit Service 646995
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
Packit Service 646995
						   EV_CONN_STOP);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		ipc_ev_clbk->put_ev_context(ev_context);
Packit Service 646995
		log_error("unknown kernel event %d", ev->type);
Packit Service 646995
		return -EEXIST;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (rc)
Packit Service 646995
		ipc_ev_clbk->put_ev_context(ev_context);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
ctldev_open(void)
Packit Service 646995
{
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	nlm_sendbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
Packit Service 646995
	if (!nlm_sendbuf) {
Packit Service 646995
		log_error("can not allocate nlm_sendbuf");
Packit Service 646995
		return -1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	nlm_recvbuf = calloc(1, NLM_BUF_DEFAULT_MAX);
Packit Service 646995
	if (!nlm_recvbuf) {
Packit Service 646995
		log_error("can not allocate nlm_recvbuf");
Packit Service 646995
		goto free_nlm_sendbuf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	pdu_sendbuf = calloc(1, PDU_SENDBUF_DEFAULT_MAX);
Packit Service 646995
	if (!pdu_sendbuf) {
Packit Service 646995
		log_error("can not allocate nlm_sendbuf");
Packit Service 646995
		goto free_nlm_recvbuf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	setparam_buf = calloc(1, NLM_SETPARAM_DEFAULT_MAX);
Packit Service 646995
	if (!setparam_buf) {
Packit Service 646995
		log_error("can not allocate setparam_buf");
Packit Service 646995
		goto free_pdu_sendbuf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	ctrl_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
Packit Service 646995
	if (ctrl_fd < 0) {
Packit Service 646995
		log_error("can not create NETLINK_ISCSI socket [%s]",
Packit Service 646995
		          strerror(errno));
Packit Service 646995
		goto free_setparam_buf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&src_addr, 0, sizeof(src_addr));
Packit Service 646995
	src_addr.nl_family = AF_NETLINK;
Packit Service 646995
	src_addr.nl_pid = getpid();
Packit Service 646995
	src_addr.nl_groups = 1;
Packit Service 646995
	if (bind(ctrl_fd, (struct sockaddr *)&src_addr, sizeof(src_addr))) {
Packit Service 646995
		log_error("can not bind NETLINK_ISCSI socket [%s]",
Packit Service 646995
		          strerror(errno));
Packit Service 646995
		goto close_socket;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&dest_addr, 0, sizeof(dest_addr));
Packit Service 646995
	dest_addr.nl_family = AF_NETLINK;
Packit Service 646995
	dest_addr.nl_pid = 0; /* kernel */
Packit Service 646995
	dest_addr.nl_groups = 0; /* unicast */
Packit Service 646995
Packit Service 646995
	log_debug(7, "created NETLINK_ISCSI socket...");
Packit Service 646995
Packit Service 646995
	return ctrl_fd;
Packit Service 646995
Packit Service 646995
close_socket:
Packit Service 646995
	close(ctrl_fd);
Packit Service 646995
free_setparam_buf:
Packit Service 646995
	free(setparam_buf);
Packit Service 646995
free_pdu_sendbuf:
Packit Service 646995
	free(pdu_sendbuf);
Packit Service 646995
free_nlm_recvbuf:
Packit Service 646995
	free(nlm_recvbuf);
Packit Service 646995
free_nlm_sendbuf:
Packit Service 646995
	free(nlm_sendbuf);
Packit Service 646995
	return -1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void
Packit Service 646995
ctldev_close(void)
Packit Service 646995
{
Packit Service 646995
	log_debug(7, "in %s", __FUNCTION__);
Packit Service 646995
Packit Service 646995
	if (ctrl_fd >= 0)
Packit Service 646995
		close(ctrl_fd);
Packit Service 646995
	free(setparam_buf);
Packit Service 646995
	free(pdu_sendbuf);
Packit Service 646995
	free(nlm_recvbuf);
Packit Service 646995
	free(nlm_sendbuf);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
struct iscsi_ipc nl_ipc = {
Packit Service 646995
	.name                   = "Open-iSCSI Kernel IPC/NETLINK v.1",
Packit Service 646995
	.ctldev_bufmax		= NLM_BUF_DEFAULT_MAX,
Packit Service 646995
	.ctldev_open		= ctldev_open,
Packit Service 646995
	.ctldev_close		= ctldev_close,
Packit Service 646995
	.ctldev_handle		= ctldev_handle,
Packit Service 646995
	.sendtargets		= ksendtargets,
Packit Service 646995
	.create_session         = kcreate_session,
Packit Service 646995
	.destroy_session        = kdestroy_session,
Packit Service 646995
	.unbind_session		= kunbind_session,
Packit Service 646995
	.create_conn            = kcreate_conn,
Packit Service 646995
	.destroy_conn           = kdestroy_conn,
Packit Service 646995
	.bind_conn              = kbind_conn,
Packit Service 646995
	.set_param              = kset_param,
Packit Service 646995
	.set_host_param		= kset_host_param,
Packit Service 646995
	.get_param              = NULL,
Packit Service 646995
	.start_conn             = kstart_conn,
Packit Service 646995
	.stop_conn              = kstop_conn,
Packit Service 646995
	.get_stats		= kget_stats,
Packit Service 646995
	.writev			= kwritev,
Packit Service 646995
	.send_pdu_begin         = ksend_pdu_begin,
Packit Service 646995
	.send_pdu_end           = ksend_pdu_end,
Packit Service 646995
	.read			= kread,
Packit Service 646995
	.recv_pdu_begin         = krecv_pdu_begin,
Packit Service 646995
	.recv_pdu_end           = krecv_pdu_end,
Packit Service 646995
	.set_net_config         = kset_net_config,
Packit Service 646995
	.recv_conn_state        = krecv_conn_state,
Packit Service 646995
	.exec_ping		= kexec_ping,
Packit Service 646995
	.get_chap		= kget_chap,
Packit Service 646995
	.set_chap		= kset_chap,
Packit Service 646995
	.delete_chap		= kdelete_chap,
Packit Service 646995
	.set_flash_node_params	= kset_flashnode_params,
Packit Service 646995
	.new_flash_node		= knew_flashnode,
Packit Service 646995
	.del_flash_node		= kdel_flashnode,
Packit Service 646995
	.login_flash_node	= klogin_flashnode,
Packit Service 646995
	.logout_flash_node	= klogout_flashnode,
Packit Service 646995
	.logout_flash_node_sid	= klogout_flashnode_sid,
Packit Service 646995
	.get_host_stats		= kget_host_stats,
Packit Service 646995
};
Packit Service 646995
struct iscsi_ipc *ipc = &nl_ipc;
Packit Service 646995
Packit Service 646995
void ipc_register_ev_callback(struct iscsi_ipc_ev_clbk *ev_clbk)
Packit Service 646995
{
Packit Service 646995
	ipc_ev_clbk = ev_clbk;
Packit Service 646995
}