Blame usr/mgmt_ipc.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI Administrator Utility Socket 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
 * Originally based on:
Packit Service 646995
 * (C) 2004 FUJITA Tomonori <tomof@acm.org>
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
#include <stdlib.h>
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <pwd.h>
Packit Service 646995
#include <sys/un.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
Packit Service 646995
#include "iscsid.h"
Packit Service 646995
#include "idbm.h"
Packit Service 646995
#include "mgmt_ipc.h"
Packit Service 646995
#include "event_poll.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
#include "iscsid_req.h"
Packit Service 646995
Packit Service 646995
#define PEERUSER_MAX	64
Packit Service 646995
#define EXTMSG_MAX	(64 * 1024)
Packit Service 646995
#define SD_SOCKET_FDS_START 3
Packit Service 646995
Packit Service 646995
int
Packit Service 646995
mgmt_ipc_listen(void)
Packit Service 646995
{
Packit Service 646995
	int fd, err, addr_len;
Packit Service 646995
	struct sockaddr_un addr;
Packit Service 646995
Packit Service 646995
	/* first check if we have fd handled by systemd */
Packit Service 646995
	fd = mgmt_ipc_systemd();
Packit Service 646995
	if (fd >= 0)
Packit Service 646995
		return fd;
Packit Service 646995
Packit Service 646995
	/* manually establish a socket */
Packit Service 646995
	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Can not create IPC socket");
Packit Service 646995
		return fd;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	addr_len = setup_abstract_addr(&addr, iscsid_namespace);
Packit Service 646995
Packit Service 646995
	if ((err = bind(fd, (struct sockaddr *) &addr, addr_len)) < 0 ) {
Packit Service 646995
		log_error("Can not bind IPC socket");
Packit Service 646995
		close(fd);
Packit Service 646995
		return err;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((err = listen(fd, 32)) < 0) {
Packit Service 646995
		log_error("Can not listen IPC socket");
Packit Service 646995
		close(fd);
Packit Service 646995
		return err;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return fd;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int mgmt_ipc_systemd(void)
Packit Service 646995
{
Packit Service 646995
	const char *env;
Packit Service 646995
Packit Service 646995
	env = getenv("LISTEN_PID");
Packit Service 646995
Packit Service 646995
	if (!env || ((pid_t)strtoul(env, NULL, 10) != getpid()))
Packit Service 646995
		return -EINVAL;
Packit Service 646995
Packit Service 646995
	env = getenv("LISTEN_FDS");
Packit Service 646995
Packit Service 646995
	if (!env)
Packit Service 646995
		return -EINVAL;
Packit Service 646995
Packit Service 646995
	if (strtoul(env, NULL, 10) != 1) {
Packit Service 646995
		log_error("Did not receive exactly one IPC socket from systemd");
Packit Service 646995
		return -EINVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return SD_SOCKET_FDS_START;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
void
Packit Service 646995
mgmt_ipc_close(int fd)
Packit Service 646995
{
Packit Service 646995
	event_loop_exit(NULL);
Packit Service 646995
	if (fd >= 0)
Packit Service 646995
		close(fd);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int 
Packit Service 646995
mgmt_ipc_session_login(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return session_login_task(&qtask->req.u.session.rec, qtask);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_session_getstats(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	int sid = qtask->req.u.session.sid;
Packit Service 646995
	iscsi_session_t *session;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	if (!(session = session_find_by_sid(sid)))
Packit Service 646995
		return ISCSI_ERR_SESS_NOT_FOUND;
Packit Service 646995
Packit Service 646995
	rc = ipc->get_stats(session->t->handle,
Packit Service 646995
		session->id, session->conn[0].id,
Packit Service 646995
		(void *)&qtask->rsp.u.getstats,
Packit Service 646995
		MGMT_IPC_GETSTATS_BUF_MAX);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("get_stats(): IPC error %d "
Packit Service 646995
			"session [%02d]", rc, sid);
Packit Service 646995
		return ISCSI_ERR_INTERNAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_send_targets(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	iscsiadm_req_t *req = &qtask->req;
Packit Service 646995
	int err;
Packit Service 646995
Packit Service 646995
	err = iscsi_host_send_targets(qtask, req->u.st.host_no,
Packit Service 646995
					  req->u.st.do_login,
Packit Service 646995
					  &req->u.st.ss);
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, err);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_session_logout(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return session_logout_task(qtask->req.u.session.sid, qtask);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_session_sync(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	struct ipc_msg_session *session= &qtask->req.u.session;
Packit Service 646995
Packit Service 646995
	return iscsi_sync_session(&session->rec, qtask, session->sid);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_cfg_initiatorname(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	if (dconfig->initiator_name)
Packit Service 646995
		strcpy(qtask->rsp.u.config.var, dconfig->initiator_name);
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_session_info(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	int sid = qtask->req.u.session.sid;
Packit Service 646995
	iscsi_session_t *session;
Packit Service 646995
	struct ipc_msg_session_state *info;
Packit Service 646995
Packit Service 646995
	if (!(session = session_find_by_sid(sid))) {
Packit Service 646995
		log_debug(1, "session with sid %d not found!", sid);
Packit Service 646995
		return ISCSI_ERR_SESS_NOT_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	info = &qtask->rsp.u.session_state;
Packit Service 646995
	info->conn_state = session->conn[0].state;
Packit Service 646995
	info->session_state = session->r_stage;
Packit Service 646995
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_cfg_initiatoralias(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	strcpy(qtask->rsp.u.config.var, dconfig->initiator_alias);
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_cfg_filename(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	strcpy(qtask->rsp.u.config.var, dconfig->config_file);
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_conn_add(__attribute__((unused))queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_ERR;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_immediate_stop(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	event_loop_exit(qtask);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_conn_remove(__attribute__((unused))queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_ERR;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * Parse a list of strings, encoded as a 32bit
Packit Service 646995
 * length followed by the string itself (not necessarily
Packit Service 646995
 * NUL-terminated).
Packit Service 646995
 */
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_parse_strings(queue_task_t *qtask, char ***result)
Packit Service 646995
{
Packit Service 646995
	char		*data, *endp, **argv = NULL;
Packit Service 646995
	unsigned int	left, argc;
Packit Service 646995
Packit Service 646995
again:
Packit Service 646995
	data = qtask->payload;
Packit Service 646995
	left = qtask->req.payload_len;
Packit Service 646995
	endp = NULL;
Packit Service 646995
	argc = 0;
Packit Service 646995
Packit Service 646995
	while (left) {
Packit Service 646995
		uint32_t len;
Packit Service 646995
Packit Service 646995
		if (left < 4)
Packit Service 646995
			return -1;
Packit Service 646995
		memcpy(&len, data, 4);
Packit Service 646995
		data += 4;
Packit Service 646995
Packit Service 646995
		if (endp)
Packit Service 646995
			*endp = '\0';
Packit Service 646995
Packit Service 646995
		if (len > left)
Packit Service 646995
			return -1;
Packit Service 646995
Packit Service 646995
		if (argv) {
Packit Service 646995
			argv[argc] = (char *) data;
Packit Service 646995
			endp = data + len;
Packit Service 646995
		}
Packit Service 646995
		data += len;
Packit Service 646995
		argc++;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (endp)
Packit Service 646995
		*endp = '\0';
Packit Service 646995
Packit Service 646995
	if (argv == NULL) {
Packit Service 646995
		argv = malloc((argc + 1) * sizeof(char *));
Packit Service 646995
		*result = argv;
Packit Service 646995
		goto again;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	argv[argc] = NULL;
Packit Service 646995
	return argc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_notify_common(queue_task_t *qtask, int (*handler)(int, char **))
Packit Service 646995
{
Packit Service 646995
	char	**argv = NULL;
Packit Service 646995
	int	argc, err = ISCSI_ERR;
Packit Service 646995
Packit Service 646995
	argc = mgmt_ipc_parse_strings(qtask, &argv);
Packit Service 646995
	if (argc > 0)
Packit Service 646995
		err = handler(argc, argv);
Packit Service 646995
Packit Service 646995
	if (argv)
Packit Service 646995
		free(argv);
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, err);
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/* Replace these dummies as you implement them
Packit Service 646995
   elsewhere */
Packit Service 646995
static int
Packit Service 646995
iscsi_discovery_add_node(__attribute__((unused))int argc,
Packit Service 646995
			 __attribute__((unused))char **argv)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
iscsi_discovery_del_node(__attribute__((unused))int argc,
Packit Service 646995
			 __attribute__((unused))char **argv)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
iscsi_discovery_add_portal(__attribute__((unused))int argc,
Packit Service 646995
			   __attribute__((unused))char **argv)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
iscsi_discovery_del_portal(__attribute__((unused))int argc,
Packit Service 646995
			   __attribute__((unused))char **argv)
Packit Service 646995
{
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_notify_add_node(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return mgmt_ipc_notify_common(qtask, iscsi_discovery_add_node);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_notify_del_node(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return mgmt_ipc_notify_common(qtask, iscsi_discovery_del_node);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_notify_add_portal(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return mgmt_ipc_notify_common(qtask, iscsi_discovery_add_portal);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_notify_del_portal(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	return mgmt_ipc_notify_common(qtask, iscsi_discovery_del_portal);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_peeruser(int sock, char *user)
Packit Service 646995
{
Packit Service 646995
	/* Linux style: use getsockopt(SO_PEERCRED) */
Packit Service 646995
	struct ucred peercred;
Packit Service 646995
	socklen_t so_len = sizeof(peercred);
Packit Service 646995
	struct passwd *pass;
Packit Service 646995
Packit Service 646995
	errno = 0;
Packit Service 646995
	if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred,
Packit Service 646995
		&so_len) != 0 || so_len != sizeof(peercred)) {
Packit Service 646995
		/* We didn't get a valid credentials struct. */
Packit Service 646995
		log_error("peeruser_unux: error receiving credentials: %m");
Packit Service 646995
		return 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	pass = getpwuid(peercred.uid);
Packit Service 646995
	if (pass == NULL) {
Packit Service 646995
		log_error("peeruser_unix: unknown local user with uid %d",
Packit Service 646995
				(int) peercred.uid);
Packit Service 646995
		return 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	strlcpy(user, pass->pw_name, PEERUSER_MAX);
Packit Service 646995
	return 1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void
Packit Service 646995
mgmt_ipc_destroy_queue_task(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	if (qtask->mgmt_ipc_fd >= 0)
Packit Service 646995
		close(qtask->mgmt_ipc_fd);
Packit Service 646995
	if (qtask->payload)
Packit Service 646995
		free(qtask->payload);
Packit Service 646995
	if (qtask->allocated)
Packit Service 646995
		free(qtask);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * Send the IPC response and destroy the queue_task.
Packit Service 646995
 * The recovery code uses a qtask which is allocated as
Packit Service 646995
 * part of a larger structure, and we don't want it to
Packit Service 646995
 * get freed when we come here. This is what qtask->allocated
Packit Service 646995
 * is for.
Packit Service 646995
 */
Packit Service 646995
void
Packit Service 646995
mgmt_ipc_write_rsp(queue_task_t *qtask, int err)
Packit Service 646995
{
Packit Service 646995
	if (!qtask)
Packit Service 646995
		return;
Packit Service 646995
	log_debug(4, "%s: rsp to fd %d", __FUNCTION__,
Packit Service 646995
		 qtask->mgmt_ipc_fd);
Packit Service 646995
Packit Service 646995
	if (qtask->mgmt_ipc_fd < 0) {
Packit Service 646995
		mgmt_ipc_destroy_queue_task(qtask);
Packit Service 646995
		return;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	qtask->rsp.err = err;
Packit Service 646995
	if (write(qtask->mgmt_ipc_fd, &qtask->rsp, sizeof(qtask->rsp)) < 0)
Packit Service 646995
		log_error("IPC qtask write failed: %s", strerror(errno));
Packit Service 646995
	mgmt_ipc_destroy_queue_task(qtask);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_read_data(int fd, void *ptr, size_t len)
Packit Service 646995
{
Packit Service 646995
	int	n;
Packit Service 646995
Packit Service 646995
	while (len) {
Packit Service 646995
		n = read(fd, ptr, len);
Packit Service 646995
		if (n < 0) {
Packit Service 646995
			if (errno == EINTR)
Packit Service 646995
				continue;
Packit Service 646995
			return -EIO;
Packit Service 646995
		}
Packit Service 646995
		if (n == 0) {
Packit Service 646995
			/* Client closed connection */
Packit Service 646995
			return -EIO;
Packit Service 646995
		}
Packit Service 646995
		ptr += n;
Packit Service 646995
		len -= n;
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
mgmt_ipc_read_req(queue_task_t *qtask)
Packit Service 646995
{
Packit Service 646995
	iscsiadm_req_t *req = &qtask->req;
Packit Service 646995
	int	rc;
Packit Service 646995
Packit Service 646995
	rc = mgmt_ipc_read_data(qtask->mgmt_ipc_fd, req, sizeof(*req));
Packit Service 646995
	if (rc >= 0 && req->payload_len > 0) {
Packit Service 646995
		/* Limit what we accept */
Packit Service 646995
		if (req->payload_len > EXTMSG_MAX)
Packit Service 646995
			return -EIO;
Packit Service 646995
Packit Service 646995
		/* Remember the allocated pointer in the
Packit Service 646995
		 * qtask - it will be freed by write_rsp.
Packit Service 646995
		 * Note: we allocate one byte in excess
Packit Service 646995
		 * so we can append a NUL byte. */
Packit Service 646995
		qtask->payload = malloc(req->payload_len + 1);
Packit Service 646995
		rc = mgmt_ipc_read_data(qtask->mgmt_ipc_fd,
Packit Service 646995
				qtask->payload,
Packit Service 646995
				req->payload_len);
Packit Service 646995
	}
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static mgmt_ipc_fn_t *	mgmt_ipc_functions[__MGMT_IPC_MAX_COMMAND] = {
Packit Service 646995
[MGMT_IPC_SESSION_LOGIN]	= mgmt_ipc_session_login,
Packit Service 646995
[MGMT_IPC_SESSION_LOGOUT]	= mgmt_ipc_session_logout,
Packit Service 646995
[MGMT_IPC_SESSION_SYNC]		= mgmt_ipc_session_sync,
Packit Service 646995
[MGMT_IPC_SESSION_STATS]	= mgmt_ipc_session_getstats,
Packit Service 646995
[MGMT_IPC_SEND_TARGETS]		= mgmt_ipc_send_targets,
Packit Service 646995
[MGMT_IPC_SESSION_INFO]		= mgmt_ipc_session_info,
Packit Service 646995
[MGMT_IPC_CONN_ADD]		= mgmt_ipc_conn_add,
Packit Service 646995
[MGMT_IPC_CONN_REMOVE]		= mgmt_ipc_conn_remove,
Packit Service 646995
[MGMT_IPC_CONFIG_INAME]		= mgmt_ipc_cfg_initiatorname,
Packit Service 646995
[MGMT_IPC_CONFIG_IALIAS]	= mgmt_ipc_cfg_initiatoralias,
Packit Service 646995
[MGMT_IPC_CONFIG_FILE]		= mgmt_ipc_cfg_filename,
Packit Service 646995
[MGMT_IPC_IMMEDIATE_STOP]	= mgmt_ipc_immediate_stop,
Packit Service 646995
[MGMT_IPC_NOTIFY_ADD_NODE]	= mgmt_ipc_notify_add_node,
Packit Service 646995
[MGMT_IPC_NOTIFY_DEL_NODE]	= mgmt_ipc_notify_del_node,
Packit Service 646995
[MGMT_IPC_NOTIFY_ADD_PORTAL]	= mgmt_ipc_notify_add_portal,
Packit Service 646995
[MGMT_IPC_NOTIFY_DEL_PORTAL]	= mgmt_ipc_notify_del_portal,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
void mgmt_ipc_handle(int accept_fd)
Packit Service 646995
{
Packit Service 646995
	unsigned int command;
Packit Service 646995
	int fd, err;
Packit Service 646995
	queue_task_t *qtask = NULL;
Packit Service 646995
	mgmt_ipc_fn_t *handler = NULL;
Packit Service 646995
	char user[PEERUSER_MAX];
Packit Service 646995
Packit Service 646995
	qtask = calloc(1, sizeof(queue_task_t));
Packit Service 646995
	if (!qtask)
Packit Service 646995
		return;
Packit Service 646995
Packit Service 646995
	if ((fd = accept(accept_fd, NULL, NULL)) < 0) {
Packit Service 646995
		free(qtask);
Packit Service 646995
		return;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	qtask->allocated = 1;
Packit Service 646995
	qtask->mgmt_ipc_fd = fd;
Packit Service 646995
Packit Service 646995
	if (!mgmt_peeruser(fd, user) || strncmp(user, "root", PEERUSER_MAX)) {
Packit Service 646995
		err = ISCSI_ERR_ACCESS;
Packit Service 646995
		goto err;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (mgmt_ipc_read_req(qtask) < 0) {
Packit Service 646995
		mgmt_ipc_destroy_queue_task(qtask);
Packit Service 646995
		return;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	command = qtask->req.command;
Packit Service 646995
	qtask->rsp.command = command;
Packit Service 646995
Packit Service 646995
	if (command > 0 &&
Packit Service 646995
	    command < __MGMT_IPC_MAX_COMMAND)
Packit Service 646995
		handler = mgmt_ipc_functions[command];
Packit Service 646995
Packit Service 646995
	if (handler != NULL) {
Packit Service 646995
		/* If the handler returns OK, this means it
Packit Service 646995
		 * already sent the reply. */
Packit Service 646995
		err = handler(qtask);
Packit Service 646995
		if (err == ISCSI_SUCCESS)
Packit Service 646995
			return;
Packit Service 646995
	} else {
Packit Service 646995
		log_error("unknown request: %s(%d) %u",
Packit Service 646995
			  __FUNCTION__, __LINE__, command);
Packit Service 646995
		err = ISCSI_ERR_INVALID_MGMT_REQ;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
err:
Packit Service 646995
	/* This will send the response, close the
Packit Service 646995
	 * connection and free the qtask */
Packit Service 646995
	mgmt_ipc_write_rsp(qtask, err);
Packit Service 646995
}