|
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 |
}
|