Blame usr/iscsiadm.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI Administration Utility
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
 * Copyright (C) 2011 Dell Inc.
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 <errno.h>
Packit Service 646995
#include <getopt.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <signal.h>
Packit Service 646995
#include <time.h>
Packit Service 646995
#include <sys/stat.h>
Packit Service 646995
#include <inttypes.h>
Packit Service 646995
Packit Service 646995
#include <libopeniscsiusr/libopeniscsiusr.h>
Packit Service 646995
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "discovery.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "mgmt_ipc.h"
Packit Service 646995
#include "idbm.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "version.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "list.h"
Packit Service 646995
#include "iscsi_settings.h"
Packit Service 646995
#include "fw_context.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
#include "session_info.h"
Packit Service 646995
#include "host.h"
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "idbm_fields.h"
Packit Service 646995
#include "session_mgmt.h"
Packit Service 646995
#include "iscsid_req.h"
Packit Service 646995
#include <libisns/isns-proto.h>
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "iscsi_timer.h"
Packit Service 646995
#include "flashnode.h"
Packit Service 646995
Packit Service 646995
#define _good(rc, rc_val, out) \
Packit Service 646995
	do { \
Packit Service 646995
		rc_val = rc; \
Packit Service 646995
		if (rc_val != LIBISCSI_OK) \
Packit Service 646995
			goto out; \
Packit Service 646995
	} while(0)
Packit Service 646995
Packit Service 646995
static char program_name[] = "iscsiadm";
Packit Service 646995
static char config_file[TARGET_NAME_MAXLEN];
Packit Service 646995
extern struct iscsi_ipc *ipc;
Packit Service 646995
Packit Service 646995
enum iscsiadm_mode {
Packit Service 646995
	MODE_DISCOVERY,
Packit Service 646995
	MODE_DISCOVERYDB,
Packit Service 646995
	MODE_NODE,
Packit Service 646995
	MODE_SESSION,
Packit Service 646995
	MODE_HOST,
Packit Service 646995
	MODE_IFACE,
Packit Service 646995
	MODE_FW,
Packit Service 646995
	MODE_PING,
Packit Service 646995
	MODE_CHAP,
Packit Service 646995
	MODE_FLASHNODE,
Packit Service 646995
	MODE_HOST_STATS
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
enum iscsiadm_op {
Packit Service 646995
	OP_NOOP			= 0x0,
Packit Service 646995
	OP_NEW			= 0x1,
Packit Service 646995
	OP_DELETE		= 0x2,
Packit Service 646995
	OP_UPDATE		= 0x4,
Packit Service 646995
	OP_SHOW			= 0x8,
Packit Service 646995
	OP_NONPERSISTENT	= 0x10,
Packit Service 646995
	OP_APPLY		= 0x20,
Packit Service 646995
	OP_APPLY_ALL		= 0x40,
Packit Service 646995
	OP_LOGIN		= 0x80,
Packit Service 646995
	OP_LOGOUT		= 0x100
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
enum _print_node_tree_mode {
Packit Service 646995
	_PRINT_MODE_IFACE,
Packit Service 646995
	_PRINT_MODE_NODE,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static struct option const long_options[] =
Packit Service 646995
{
Packit Service 646995
	{"mode", required_argument, NULL, 'm'},
Packit Service 646995
	{"portal", required_argument, NULL, 'p'},
Packit Service 646995
	{"targetname", required_argument, NULL, 'T'},
Packit Service 646995
	{"interface", required_argument, NULL, 'I'},
Packit Service 646995
	{"op", required_argument, NULL, 'o'},
Packit Service 646995
	{"type", required_argument, NULL, 't'},
Packit Service 646995
	{"name", required_argument, NULL, 'n'},
Packit Service 646995
	{"value", required_argument, NULL, 'v'},
Packit Service 646995
	{"host", required_argument, NULL, 'H'},
Packit Service 646995
	{"sid", required_argument, NULL, 'r'},
Packit Service 646995
	{"rescan", no_argument, NULL, 'R'},
Packit Service 646995
	{"print", required_argument, NULL, 'P'},
Packit Service 646995
	{"discover", no_argument, NULL, 'D'},
Packit Service 646995
	{"login", no_argument, NULL, 'l'},
Packit Service 646995
	{"loginall", required_argument, NULL, 'L'},
Packit Service 646995
	{"logout", no_argument, NULL, 'u'},
Packit Service 646995
	{"logoutall", required_argument, NULL, 'U'},
Packit Service 646995
	{"stats", no_argument, NULL, 's'},
Packit Service 646995
	{"killiscsid", required_argument, NULL, 'k'},
Packit Service 646995
	{"debug", required_argument, NULL, 'd'},
Packit Service 646995
	{"show", no_argument, NULL, 'S'},
Packit Service 646995
	{"version", no_argument, NULL, 'V'},
Packit Service 646995
	{"help", no_argument, NULL, 'h'},
Packit Service 646995
	{"submode", required_argument, NULL, 'C'},
Packit Service 646995
	{"ip", required_argument, NULL, 'a'},
Packit Service 646995
	{"packetsize", required_argument, NULL, 'b'},
Packit Service 646995
	{"count", required_argument, NULL, 'c'},
Packit Service 646995
	{"interval", required_argument, NULL, 'i'},
Packit Service 646995
	{"index", required_argument, NULL, 'x'},
Packit Service 646995
	{"portal_type", optional_argument, NULL, 'A'},
Packit Service 646995
	{"no_wait", no_argument, NULL, 'W'},
Packit Service 646995
	{NULL, 0, NULL, 0},
Packit Service 646995
};
Packit Service 646995
static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:ux:A:W";
Packit Service 646995
Packit Service 646995
static void usage(int status)
Packit Service 646995
{
Packit Service 646995
	if (status != 0)
Packit Service 646995
		fprintf(stderr, "Try `%s --help' for more information.\n",
Packit Service 646995
			program_name);
Packit Service 646995
	else {
Packit Service 646995
		printf("\
Packit Service 646995
iscsiadm -m discoverydb [-hV] [-d debug_level] [-P printlevel] [-t type -p ip:port -I ifaceN ... [-Dl]] | [[-p ip:port -t type] \
Packit Service 646995
[-o operation] [-n name] [-v value] [-lD]] \n\
Packit Service 646995
iscsiadm -m discovery [-hV] [-d debug_level] [-P printlevel] [-t type -p ip:port -I ifaceN ... [-l]] | [[-p ip:port] [-l | -D]] \n\
Packit Service 646995
iscsiadm -m node [-hV] [-d debug_level] [-P printlevel] [-L all,manual,automatic,onboot] [-W] [-U all,manual,automatic,onboot] [-S] [[-T targetname -p ip:port -I ifaceN] [-l | -u | -R | -s]] \
Packit Service 646995
[[-o  operation ] [-n name] [-v value]]\n\
Packit Service 646995
iscsiadm -m session [-hV] [-d debug_level] [-P  printlevel] [-r sessionid | sysfsdir [-R | -u | -s] [-o operation] [-n name] [-v value]]\n\
Packit Service 646995
iscsiadm -m iface [-hV] [-d debug_level] [-P printlevel] [-I ifacename | -H hostno|MAC] [[-o  operation ] [-n name] [-v value]] [-C ping [-a ip] [-b packetsize] [-c count] [-i interval]]\n\
Packit Service 646995
iscsiadm -m fw [-d debug_level] [-l]\n\
Packit Service 646995
iscsiadm -m host [-P printlevel] [-H hostno|MAC] [[-C chap [-x chap_tbl_idx]] | [-C flashnode [-A portal_type] [-x flashnode_idx]] | [-C stats]] [[-o operation] [-n name] [-v value]] \n\
Packit Service 646995
iscsiadm -k priority\n");
Packit Service 646995
	}
Packit Service 646995
	exit(status);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
str_to_op(char *str)
Packit Service 646995
{
Packit Service 646995
	int op;
Packit Service 646995
Packit Service 646995
	if (!strcmp("new", str))
Packit Service 646995
		op = OP_NEW;
Packit Service 646995
	else if (!strcmp("delete", str))
Packit Service 646995
		op = OP_DELETE;
Packit Service 646995
	else if (!strcmp("update", str))
Packit Service 646995
		op = OP_UPDATE;
Packit Service 646995
	else if (!strcmp("show", str))
Packit Service 646995
		op = OP_SHOW;
Packit Service 646995
	else if (!strcmp("nonpersistent", str))
Packit Service 646995
		op = OP_NONPERSISTENT;
Packit Service 646995
	else if (!strcmp("apply", str))
Packit Service 646995
		op = OP_APPLY;
Packit Service 646995
	else if (!strcmp("applyall", str))
Packit Service 646995
		op = OP_APPLY_ALL;
Packit Service 646995
	else if (!strcmp("login", str))
Packit Service 646995
		op = OP_LOGIN;
Packit Service 646995
	else if (!strcmp("logout", str))
Packit Service 646995
		op = OP_LOGOUT;
Packit Service 646995
	else
Packit Service 646995
		op = OP_NOOP;
Packit Service 646995
Packit Service 646995
	return op;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
str_to_mode(char *str)
Packit Service 646995
{
Packit Service 646995
	int mode;
Packit Service 646995
Packit Service 646995
	if (!strcmp("discovery", str))
Packit Service 646995
		mode = MODE_DISCOVERY;
Packit Service 646995
	else if (!strcmp("discoverydb", str))
Packit Service 646995
		mode = MODE_DISCOVERYDB;
Packit Service 646995
	else if (!strcmp("node", str))
Packit Service 646995
		mode = MODE_NODE;
Packit Service 646995
	else if (!strcmp("session", str))
Packit Service 646995
		mode = MODE_SESSION;
Packit Service 646995
	else if (!strcmp("iface", str))
Packit Service 646995
		mode = MODE_IFACE;
Packit Service 646995
	else if (!strcmp("fw", str))
Packit Service 646995
		mode = MODE_FW;
Packit Service 646995
	else if (!strcmp("host", str))
Packit Service 646995
		mode = MODE_HOST;
Packit Service 646995
	else
Packit Service 646995
		mode = -1;
Packit Service 646995
Packit Service 646995
	return mode;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
str_to_submode(char *str)
Packit Service 646995
{
Packit Service 646995
	int sub_mode;
Packit Service 646995
Packit Service 646995
	if (!strcmp("ping", str))
Packit Service 646995
		sub_mode = MODE_PING;
Packit Service 646995
	else if (!strcmp("chap", str))
Packit Service 646995
		sub_mode = MODE_CHAP;
Packit Service 646995
	else if (!strcmp("flashnode", str))
Packit Service 646995
		sub_mode = MODE_FLASHNODE;
Packit Service 646995
	else if (!strcmp("stats", str))
Packit Service 646995
		sub_mode = MODE_HOST_STATS;
Packit Service 646995
Packit Service 646995
	else
Packit Service 646995
		sub_mode = -1;
Packit Service 646995
Packit Service 646995
	return sub_mode;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
str_to_type(char *str)
Packit Service 646995
{
Packit Service 646995
	int type;
Packit Service 646995
Packit Service 646995
	if (!strcmp("sendtargets", str) ||
Packit Service 646995
	    !strcmp("st", str))
Packit Service 646995
		type = DISCOVERY_TYPE_SENDTARGETS;
Packit Service 646995
	else if (!strcmp("slp", str))
Packit Service 646995
		type = DISCOVERY_TYPE_SLP;
Packit Service 646995
	else if (!strcmp("isns", str))
Packit Service 646995
		type = DISCOVERY_TYPE_ISNS;
Packit Service 646995
	else if (!strcmp("fw", str))
Packit Service 646995
		type = DISCOVERY_TYPE_FW;
Packit Service 646995
	else
Packit Service 646995
		type = -1;
Packit Service 646995
Packit Service 646995
	return type;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
str_to_portal_type(char *str)
Packit Service 646995
{
Packit Service 646995
	int ptype;
Packit Service 646995
Packit Service 646995
	if (!strcmp("ipv4", str))
Packit Service 646995
		ptype = IPV4;
Packit Service 646995
	else if (!strcmp("ipv6", str))
Packit Service 646995
		ptype = IPV6;
Packit Service 646995
	else
Packit Service 646995
		ptype = -1;
Packit Service 646995
Packit Service 646995
	return ptype;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void kill_iscsid(int priority, int tmo)
Packit Service 646995
{
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * We only support SIGTERM like stoppage of iscsid for now.
Packit Service 646995
	 * In the future we can do something where we try go finish
Packit Service 646995
	 * up operations like login, error handling, etc, before
Packit Service 646995
	 * iscsid is stopped, and we can add different values to indicate
Packit Service 646995
	 * that the user wants iscsid to log out existing sessions before
Packit Service 646995
	 * exiting.
Packit Service 646995
	 */
Packit Service 646995
	if (priority != 0) {
Packit Service 646995
		log_error("Invalid iscsid priority %d. Priority must be 0.",
Packit Service 646995
			  priority);
Packit Service 646995
		return;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_IMMEDIATE_STOP;
Packit Service 646995
	rc = iscsid_exec_req(&req, &rsp, 0, tmo);
Packit Service 646995
	if (rc) {
Packit Service 646995
		iscsi_err_print_msg(rc);
Packit Service 646995
		log_error("Could not stop iscsid. Trying sending iscsid "
Packit Service 646995
			  "SIGTERM or SIGKILL signals manually");
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
match_startup_mode(node_rec_t *rec, char *mode)
Packit Service 646995
{
Packit Service 646995
	if ((!strcmp(mode, "automatic") &&
Packit Service 646995
	    rec->startup == ISCSI_STARTUP_AUTOMATIC) ||
Packit Service 646995
	    (!strcmp(mode, "onboot") &&
Packit Service 646995
	    rec->startup == ISCSI_STARTUP_ONBOOT) ||
Packit Service 646995
	    (!strcmp(mode, "manual") &&
Packit Service 646995
	    rec->startup == ISCSI_STARTUP_MANUAL) ||
Packit Service 646995
	    !strcmp(mode, "all"))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	/* support conn or session startup params */
Packit Service 646995
	if ((!strcmp(mode, "automatic") &&
Packit Service 646995
	    rec->conn[0].startup == ISCSI_STARTUP_AUTOMATIC) ||
Packit Service 646995
	    (!strcmp(mode, "onboot") &&
Packit Service 646995
	    rec->conn[0].startup == ISCSI_STARTUP_ONBOOT) ||
Packit Service 646995
	    (!strcmp(mode, "manual") &&
Packit Service 646995
	    rec->conn[0].startup == ISCSI_STARTUP_MANUAL) ||
Packit Service 646995
	    !strcmp(mode, "all"))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	return -1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
for_each_session(struct node_rec *rec, iscsi_sysfs_session_op_fn *fn,
Packit Service 646995
		 int in_parallel)
Packit Service 646995
{
Packit Service 646995
	int err, num_found = 0;
Packit Service 646995
Packit Service 646995
	if (rec && rec->session.info) {
Packit Service 646995
		num_found = 1;
Packit Service 646995
		err = fn(rec, rec->session.info);
Packit Service 646995
	} else {
Packit Service 646995
		err = iscsi_sysfs_for_each_session(rec, &num_found, fn,
Packit Service 646995
						   in_parallel);
Packit Service 646995
	}
Packit Service 646995
	if (err)
Packit Service 646995
		log_error("Could not execute operation on all sessions: %s",
Packit Service 646995
			  iscsi_err_to_str(err));
Packit Service 646995
	else if (!num_found) {
Packit Service 646995
		log_error("No session found.");
Packit Service 646995
		err = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return err;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int link_recs(void *data, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct list_head *list = data;
Packit Service 646995
	struct node_rec *rec_copy;
Packit Service 646995
Packit Service 646995
	rec_copy = calloc(1, sizeof(*rec_copy));
Packit Service 646995
	if (!rec_copy)
Packit Service 646995
		return ISCSI_ERR_NOMEM;
Packit Service 646995
	memcpy(rec_copy, rec, sizeof(*rec_copy));
Packit Service 646995
	INIT_LIST_HEAD(&rec_copy->list);
Packit Service 646995
	list_add_tail(&rec_copy->list, list);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
__logout_by_startup(void *data, struct list_head *list,
Packit Service 646995
		    struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	char *mode = data;
Packit Service 646995
	node_rec_t rec;
Packit Service 646995
Packit Service 646995
	memset(&rec, 0, sizeof(node_rec_t));
Packit Service 646995
	if (idbm_rec_read(&rec, info->targetname, info->tpgt,
Packit Service 646995
			  info->persistent_address,
Packit Service 646995
			  info->persistent_port, &info->iface, false)) {
Packit Service 646995
		/*
Packit Service 646995
		 * this is due to a HW driver or some other driver
Packit Service 646995
		 * not hooked in
Packit Service 646995
		 */
Packit Service 646995
		log_debug(7, "could not read data for [%s,%s.%d]",
Packit Service 646995
			  info->targetname, info->persistent_address,
Packit Service 646995
			  info->persistent_port);
Packit Service 646995
		return -1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* multiple drivers could be connected to the same portal */
Packit Service 646995
	if (strcmp(rec.iface.transport_name, info->iface.transport_name))
Packit Service 646995
		return -1;
Packit Service 646995
	/*
Packit Service 646995
	 * we always skip on boot because if the user killed this on
Packit Service 646995
	 * they would not be able to do anything
Packit Service 646995
	 */
Packit Service 646995
	if (rec.startup == ISCSI_STARTUP_ONBOOT)
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	if (rec.disc_type == DISCOVERY_TYPE_FW)
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	if (match_startup_mode(&rec, mode))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	return iscsi_logout_portal(info, list);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
logout_by_startup(char *mode)
Packit Service 646995
{
Packit Service 646995
	int nr_found;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
Packit Service 646995
	    !strcmp(mode,"manual"))) {
Packit Service 646995
		log_error("Invalid logoutall option %s.", mode);
Packit Service 646995
		usage(ISCSI_ERR_INVAL);
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = iscsi_logout_portals(mode, &nr_found, 1, __logout_by_startup);
Packit Service 646995
	if (rc == ISCSI_ERR_NO_OBJS_FOUND)
Packit Service 646995
		log_error("No matching sessions found");
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
struct startup_data {
Packit Service 646995
	char *mode;
Packit Service 646995
	struct list_head all_logins;
Packit Service 646995
	struct list_head leading_logins;
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static int link_startup_recs(void *data, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct startup_data *startup = data;
Packit Service 646995
	struct node_rec *rec_copy;
Packit Service 646995
Packit Service 646995
	if (match_startup_mode(rec, startup->mode))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	rec_copy = calloc(1, sizeof(*rec_copy));
Packit Service 646995
	if (!rec_copy)
Packit Service 646995
		return ISCSI_ERR_NOMEM;
Packit Service 646995
	memcpy(rec_copy, rec, sizeof(*rec_copy));
Packit Service 646995
	INIT_LIST_HEAD(&rec_copy->list);
Packit Service 646995
Packit Service 646995
	if (rec_copy->leading_login)
Packit Service 646995
		list_add_tail(&rec_copy->list, &startup->leading_logins);
Packit Service 646995
	else
Packit Service 646995
		list_add_tail(&rec_copy->list, &startup->all_logins);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
__do_leading_login(void *data, struct list_head *list, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct iface_rec *pattern_iface = data;
Packit Service 646995
	int nr_found;
Packit Service 646995
Packit Service 646995
	log_debug(1, "doing leading login using iface: %s", pattern_iface->name);
Packit Service 646995
Packit Service 646995
	/* Skip any records that do not match the pattern iface */
Packit Service 646995
	if (!iface_match(pattern_iface, &rec->iface))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * If there is an existing session that matcthes the target,
Packit Service 646995
	 * the leading login is complete.
Packit Service 646995
	 */
Packit Service 646995
	if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_target, 0)) {
Packit Service 646995
		log_debug(1, "Skipping %s: Already a session for that target",
Packit Service 646995
			  rec->name);
Packit Service 646995
		return -1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* No existing session: Attempt a login. */
Packit Service 646995
	return iscsi_login_portal(NULL, list, rec);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
login_by_startup(char *mode, bool wait)
Packit Service 646995
{
Packit Service 646995
	int nr_found = 0, err, rc;
Packit Service 646995
	struct startup_data startup;
Packit Service 646995
Packit Service 646995
	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
Packit Service 646995
		       !strcmp(mode,"manual") || !strcmp(mode, "onboot"))) {
Packit Service 646995
		log_error("Invalid loginall option %s.", mode);
Packit Service 646995
		usage(ISCSI_ERR_INVAL);
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * Filter all node records that match the given 'mode' into 2 lists:
Packit Service 646995
	 * Those with leading_login enabled, and those without.
Packit Service 646995
	 */
Packit Service 646995
	startup.mode = mode;
Packit Service 646995
	INIT_LIST_HEAD(&startup.all_logins);
Packit Service 646995
	INIT_LIST_HEAD(&startup.leading_logins);
Packit Service 646995
	err = idbm_for_each_rec(&nr_found, &startup, link_startup_recs, false);
Packit Service 646995
	if (err && (!list_empty(&startup.all_logins) ||
Packit Service 646995
		    !list_empty(&startup.leading_logins)))
Packit Service 646995
		/* log msg and try to log into what we found */
Packit Service 646995
		log_error("Could not read all records: %s",
Packit Service 646995
			  iscsi_err_to_str(err));
Packit Service 646995
	else if (list_empty(&startup.all_logins) &&
Packit Service 646995
		 list_empty(&startup.leading_logins)) {
Packit Service 646995
		if (err) {
Packit Service 646995
			log_error("Could not read node DB: %s.",
Packit Service 646995
				  iscsi_err_to_str(err));
Packit Service 646995
		} else {
Packit Service 646995
			log_error("No records found");
Packit Service 646995
			err = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
		}
Packit Service 646995
		return err;
Packit Service 646995
	}
Packit Service 646995
	rc = err;
Packit Service 646995
Packit Service 646995
	if (!list_empty(&startup.all_logins)) {
Packit Service 646995
		log_debug(1, "Logging into normal (non-leading-login) portals");
Packit Service 646995
		/* Login all regular (non-leading-login) portals first */
Packit Service 646995
		err = iscsi_login_portals(NULL, &nr_found, wait,
Packit Service 646995
				&startup.all_logins, iscsi_login_portal);
Packit Service 646995
		if (err)
Packit Service 646995
			log_error("Could not log into all portals");
Packit Service 646995
		if (err && !rc)
Packit Service 646995
			rc = err;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!list_empty(&startup.leading_logins)) {
Packit Service 646995
		/*
Packit Service 646995
		 * For each iface in turn, try to login all portals on that
Packit Service 646995
		 * iface that do not already have a session present.
Packit Service 646995
		 */
Packit Service 646995
		struct iface_rec *pattern_iface, *tmp_iface;
Packit Service 646995
		struct node_rec *rec, *tmp_rec;
Packit Service 646995
		LIST_HEAD(iface_list);
Packit Service 646995
		int missed_leading_login = 0;
Packit Service 646995
		log_debug(1, "Logging into leading-login portals");
Packit Service 646995
		iface_link_ifaces(&iface_list);
Packit Service 646995
		list_for_each_entry_safe(pattern_iface, tmp_iface, &iface_list,
Packit Service 646995
					 list) {
Packit Service 646995
			log_debug(1, "Establishing leading-logins via iface %s",
Packit Service 646995
				  pattern_iface->name);
Packit Service 646995
			err = iscsi_login_portals_safe(pattern_iface, &nr_found,
Packit Service 646995
						       1,
Packit Service 646995
						       &startup.leading_logins,
Packit Service 646995
						       __do_leading_login);
Packit Service 646995
			if (err)
Packit Service 646995
				log_error("Could not log into all portals on "
Packit Service 646995
					  "%s, trying next interface",
Packit Service 646995
					  pattern_iface->name);
Packit Service 646995
Packit Service 646995
			/*
Packit Service 646995
			 * Note: We always try all iface records in case there
Packit Service 646995
			 * are targets that are associated with only a subset
Packit Service 646995
			 * of iface records.  __do_leading_login already
Packit Service 646995
			 * prevents duplicate sessions if an iface has succeeded
Packit Service 646995
			 * for a particular target.
Packit Service 646995
			 */
Packit Service 646995
		}
Packit Service 646995
		/*
Packit Service 646995
		 * Double-check that all leading-login portals have at least
Packit Service 646995
		 * one session
Packit Service 646995
		 */
Packit Service 646995
		list_for_each_entry_safe(rec, tmp_rec, &startup.leading_logins,
Packit Service 646995
					 list) {
Packit Service 646995
			if (!iscsi_sysfs_for_each_session(rec, &nr_found,
Packit Service 646995
							  iscsi_match_target, 0))
Packit Service 646995
				missed_leading_login++;
Packit Service 646995
			/*
Packit Service 646995
			 * Cleanup the list, since 'iscsi_login_portals_safe'
Packit Service 646995
			 * does not
Packit Service 646995
			 */
Packit Service 646995
			list_del(&rec->list);
Packit Service 646995
			free(rec);
Packit Service 646995
		}
Packit Service 646995
		if (missed_leading_login) {
Packit Service 646995
			log_error("Could not login all leading-login portals");
Packit Service 646995
			if (!rc)
Packit Service 646995
				rc = ISCSI_ERR_FATAL_LOGIN;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/**
Packit Service 646995
 * iscsi_logout_matched_portal - logout of targets matching the rec info
Packit Service 646995
 * @data: record to session with
Packit Service 646995
 * @list: list to add logout rec to
Packit Service 646995
 * @info: session to match with rec
Packit Service 646995
 */
Packit Service 646995
static int iscsi_logout_matched_portal(void *data, struct list_head *list,
Packit Service 646995
				       struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	struct node_rec *pattern_rec = data;
Packit Service 646995
	struct iscsi_transport *t;
Packit Service 646995
	uint32_t host_no;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_sid(info->sid);
Packit Service 646995
	if (!t)
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	if (!iscsi_match_session(pattern_rec, info))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &rc);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("could not get host_no for session%d: %s.",
Packit Service 646995
			  info->sid, iscsi_err_to_str(rc));
Packit Service 646995
		return -1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!iscsi_sysfs_session_user_created(info->sid))
Packit Service 646995
		rc = iscsi_logout_flashnode_sid(t, host_no, info->sid);
Packit Service 646995
	else
Packit Service 646995
		rc = iscsi_logout_portal(info, list);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int rec_match_fn(void *data, node_rec_t *rec)
Packit Service 646995
{
Packit Service 646995
	struct rec_op_data *op_data = data;
Packit Service 646995
Packit Service 646995
	if (!__iscsi_match_session(op_data->match_rec, rec->name,
Packit Service 646995
				   rec->conn[0].address, rec->conn[0].port,
Packit Service 646995
				   &rec->iface, rec->session.sid))
Packit Service 646995
		return -1;
Packit Service 646995
	return op_data->fn(op_data->data, rec);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int __for_each_matched_rec(int verbose, struct node_rec *rec,
Packit Service 646995
				  void *data, idbm_iface_op_fn *fn)
Packit Service 646995
{
Packit Service 646995
	struct rec_op_data op_data;
Packit Service 646995
	int nr_found = 0, rc;
Packit Service 646995
Packit Service 646995
	memset(&op_data, 0, sizeof(struct rec_op_data));
Packit Service 646995
	op_data.data = data;
Packit Service 646995
	op_data.match_rec = rec;
Packit Service 646995
	op_data.fn = fn;
Packit Service 646995
Packit Service 646995
	rc = idbm_for_each_rec(&nr_found, &op_data, rec_match_fn, true);
Packit Service 646995
	if (rc) {
Packit Service 646995
		if (verbose)
Packit Service 646995
			log_error("Could not execute operation on all "
Packit Service 646995
				  "records: %s", iscsi_err_to_str(rc));
Packit Service 646995
	} else if (!nr_found) {
Packit Service 646995
		if (verbose)
Packit Service 646995
			log_error("No records found");
Packit Service 646995
		rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int for_each_matched_rec(struct node_rec *rec, void *data,
Packit Service 646995
			        idbm_iface_op_fn *fn)
Packit Service 646995
{
Packit Service 646995
	return __for_each_matched_rec(1, rec, data, fn);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
Packit Service 646995
static int login_portals(struct node_rec *pattern_rec, bool wait)
Packit Service 646995
{
Packit Service 646995
	LIST_HEAD(rec_list);
Packit Service 646995
	int nr_found, rc, err;
Packit Service 646995
Packit Service 646995
	err = for_each_matched_rec(pattern_rec, &rec_list, link_recs);
Packit Service 646995
	if (err == ISCSI_ERR_NO_OBJS_FOUND)
Packit Service 646995
		return err;
Packit Service 646995
	else if (err && list_empty(&rec_list))
Packit Service 646995
		return err;
Packit Service 646995
Packit Service 646995
	rc = err;
Packit Service 646995
	/* if there is an err but some recs then try to login to what we have */
Packit Service 646995
Packit Service 646995
	err = iscsi_login_portals(pattern_rec, &nr_found, wait ? 1 : 0, &rec_list,
Packit Service 646995
				  iscsi_login_portal);
Packit Service 646995
	if (err)
Packit Service 646995
		log_error("Could not log into all portals");
Packit Service 646995
Packit Service 646995
	if (err && !rc)
Packit Service 646995
		rc = err;
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void print_node_flat(struct iscsi_node *node)
Packit Service 646995
{
Packit Service 646995
		printf("%s,%" PRIu16 " %s\n",
Packit Service 646995
		       iscsi_node_portal_get(node),
Packit Service 646995
		       iscsi_node_tpgt_get(node),
Packit Service 646995
		       iscsi_node_target_name_get(node));
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void print_nodes_tree(struct iscsi_node **nodes, uint32_t node_count,
Packit Service 646995
			     enum _print_node_tree_mode print_mode)
Packit Service 646995
{
Packit Service 646995
	unsigned int i;
Packit Service 646995
	struct iscsi_node *cur_node = NULL;
Packit Service 646995
	struct iscsi_node *prev_node = NULL;
Packit Service 646995
	const char *prefix = NULL;
Packit Service 646995
Packit Service 646995
	if (print_mode == _PRINT_MODE_IFACE)
Packit Service 646995
		prefix = "\t";
Packit Service 646995
	else
Packit Service 646995
		prefix = "";
Packit Service 646995
Packit Service 646995
	// According to libopeniscsiusr document, nodes are sorted. There
Packit Service 646995
	// is no need to create hash table for this.
Packit Service 646995
	for (i = 0; i < node_count; ++i) {
Packit Service 646995
		cur_node = nodes[i];
Packit Service 646995
		/*
Packit Service 646995
		 * Print the target line if this is our first pass, or
Packit Service 646995
		 * if if it does not match the prevous target. Always print
Packit Service 646995
		 * the Portal line. The original code seemed to want to
Packit Service 646995
		 * suppres duplicates here, as well, but it evidently
Packit Service 646995
		 * didn't work that way, so let's not regress output format
Packit Service 646995
		 */
Packit Service 646995
		if (!prev_node || strcmp(iscsi_node_target_name_get(prev_node),
Packit Service 646995
					 iscsi_node_target_name_get(cur_node)))
Packit Service 646995
			printf("%sTarget: %s\n", prefix,
Packit Service 646995
			       iscsi_node_target_name_get(cur_node));
Packit Service 646995
		printf("%s\tPortal: %s,%d\n", prefix,
Packit Service 646995
		       iscsi_node_portal_get(cur_node),
Packit Service 646995
		       iscsi_node_tpgt_get(cur_node));
Packit Service 646995
		if (print_mode == _PRINT_MODE_NODE)
Packit Service 646995
			printf("\t\tIface Name: %s\n",
Packit Service 646995
			       iscsi_node_iface_name_get(cur_node));
Packit Service 646995
		prev_node = cur_node;
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int print_nodes(struct iscsi_context *ctx, int info_level)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_node **nodes = NULL;
Packit Service 646995
	uint32_t node_count = 0;
Packit Service 646995
	uint32_t i = 0;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	if ((info_level != 0) && (info_level != -1) && (info_level != 1)) {
Packit Service 646995
		log_error("Invalid info level %d. Try 0 or 1.", info_level);
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = iscsi_nodes_get(ctx, &nodes, &node_count);
Packit Service 646995
	if (rc != LIBISCSI_OK)
Packit Service 646995
		goto out;
Packit Service 646995
Packit Service 646995
	if (!node_count) {
Packit Service 646995
		log_error("No records found");
Packit Service 646995
		rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (info_level == 1)
Packit Service 646995
		print_nodes_tree(nodes, node_count, _PRINT_MODE_NODE);
Packit Service 646995
	else
Packit Service 646995
		for (i = 0; i < node_count; ++i)
Packit Service 646995
			print_node_flat(nodes[i]);
Packit Service 646995
Packit Service 646995
out:
Packit Service 646995
	iscsi_nodes_free(nodes, node_count);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int print_nodes_config(struct iscsi_context *ctx, bool show_secret,
Packit Service 646995
			      const char *target_name, const char *address,
Packit Service 646995
			      int32_t port, const char *iface_name)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	struct iscsi_node **nodes = NULL;
Packit Service 646995
	struct iscsi_node *node = NULL;
Packit Service 646995
	uint32_t node_count = 0;
Packit Service 646995
	uint32_t i = 0;
Packit Service 646995
	bool match = false;
Packit Service 646995
	bool has_match = false;
Packit Service 646995
Packit Service 646995
	rc = iscsi_nodes_get(ctx, &nodes, &node_count);
Packit Service 646995
	if (rc != LIBISCSI_OK)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	for (i = 0; i < node_count; ++i) {
Packit Service 646995
		node = nodes[i];
Packit Service 646995
		match = true;
Packit Service 646995
		if ((target_name != NULL) &&
Packit Service 646995
		    (strlen(target_name) != 0) &&
Packit Service 646995
		    (strcmp(target_name,
Packit Service 646995
			    iscsi_node_target_name_get(node)) != 0))
Packit Service 646995
			match = false;
Packit Service 646995
		if ((address != NULL) &&
Packit Service 646995
		    (strlen(address) != 0) &&
Packit Service 646995
		    (strcmp(address, iscsi_node_conn_address_get(node)) != 0))
Packit Service 646995
			match = false;
Packit Service 646995
		if ((port != -1) && (port != (int32_t)iscsi_node_conn_port_get(node)))
Packit Service 646995
			match = false;
Packit Service 646995
		if ((iface_name != NULL) &&
Packit Service 646995
		    (strlen(iface_name) != 0) &&
Packit Service 646995
		    (strcmp(iface_name, iscsi_node_iface_name_get(node)) != 0))
Packit Service 646995
			match = false;
Packit Service 646995
Packit Service 646995
		if (match == true) {
Packit Service 646995
			iscsi_node_print_config(node, show_secret);
Packit Service 646995
			has_match = true;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	iscsi_nodes_free(nodes, node_count);
Packit Service 646995
Packit Service 646995
	if (has_match == false) {
Packit Service 646995
		log_error("No records found");
Packit Service 646995
		rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static char *get_config_file(void)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_CONFIG_FILE;
Packit Service 646995
Packit Service 646995
	rc = iscsid_exec_req(&req, &rsp, 1, ISCSID_REQ_TIMEOUT);
Packit Service 646995
	if (rc)
Packit Service 646995
		return NULL;
Packit Service 646995
Packit Service 646995
	if (rsp.u.config.var[0] != '\0') {
Packit Service 646995
		strcpy(config_file, rsp.u.config.var);
Packit Service 646995
		return config_file;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return NULL;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int rescan_portal(void *data, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	int host_no, err;
Packit Service 646995
Packit Service 646995
	if (!iscsi_match_session(data, info))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	printf("Rescanning session [sid: %d, target: %s, portal: "
Packit Service 646995
		"%s,%d]\n", info->sid, info->targetname,
Packit Service 646995
		info->persistent_address, info->port);
Packit Service 646995
Packit Service 646995
	host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &err;;
Packit Service 646995
	if (err) {
Packit Service 646995
		log_error("Could not rescan session sid %d.", info->sid);
Packit Service 646995
		return err;
Packit Service 646995
	}
Packit Service 646995
	/* rescan each device to pick up size changes */
Packit Service 646995
	iscsi_sysfs_for_each_device(NULL, host_no, info->sid,
Packit Service 646995
				    iscsi_sysfs_rescan_device);
Packit Service 646995
	/* now scan for new devices */
Packit Service 646995
	iscsi_sysfs_scan_host(host_no, 0, 1);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
session_stats(void *data, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	int rc, i;
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
Packit Service 646995
	if (!iscsi_match_session(data, info))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_SESSION_STATS;
Packit Service 646995
	req.u.session.sid = info->sid;
Packit Service 646995
Packit Service 646995
	rc = iscsid_exec_req(&req, &rsp, 1, info->iscsid_req_tmo);
Packit Service 646995
	if (rc)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	printf("Stats for session [sid: %d, target: %s, portal: "
Packit Service 646995
		"%s,%d]\n",
Packit Service 646995
		info->sid, info->targetname, info->persistent_address,
Packit Service 646995
		info->port);
Packit Service 646995
Packit Service 646995
	printf( "iSCSI SNMP:\n"
Packit Service 646995
Packit Service 646995
		"\ttxdata_octets: %lld\n"
Packit Service 646995
		"\trxdata_octets: %lld\n"
Packit Service 646995
Packit Service 646995
		"\tnoptx_pdus: %u\n"
Packit Service 646995
		"\tscsicmd_pdus: %u\n"
Packit Service 646995
		"\ttmfcmd_pdus: %u\n"
Packit Service 646995
		"\tlogin_pdus: %u\n"
Packit Service 646995
		"\ttext_pdus: %u\n"
Packit Service 646995
		"\tdataout_pdus: %u\n"
Packit Service 646995
		"\tlogout_pdus: %u\n"
Packit Service 646995
		"\tsnack_pdus: %u\n"
Packit Service 646995
Packit Service 646995
		"\tnoprx_pdus: %u\n"
Packit Service 646995
		"\tscsirsp_pdus: %u\n"
Packit Service 646995
		"\ttmfrsp_pdus: %u\n"
Packit Service 646995
		"\ttextrsp_pdus: %u\n"
Packit Service 646995
		"\tdatain_pdus: %u\n"
Packit Service 646995
		"\tlogoutrsp_pdus: %u\n"
Packit Service 646995
		"\tr2t_pdus: %u\n"
Packit Service 646995
		"\tasync_pdus: %u\n"
Packit Service 646995
		"\trjt_pdus: %u\n"
Packit Service 646995
Packit Service 646995
		"\tdigest_err: %u\n"
Packit Service 646995
		"\ttimeout_err: %u\n",
Packit Service 646995
		(unsigned long long)rsp.u.getstats.stats.txdata_octets,
Packit Service 646995
		(unsigned long long)rsp.u.getstats.stats.rxdata_octets,
Packit Service 646995
Packit Service 646995
		rsp.u.getstats.stats.noptx_pdus,
Packit Service 646995
		rsp.u.getstats.stats.scsicmd_pdus,
Packit Service 646995
		rsp.u.getstats.stats.tmfcmd_pdus,
Packit Service 646995
		rsp.u.getstats.stats.login_pdus,
Packit Service 646995
		rsp.u.getstats.stats.text_pdus,
Packit Service 646995
		rsp.u.getstats.stats.dataout_pdus,
Packit Service 646995
		rsp.u.getstats.stats.logout_pdus,
Packit Service 646995
		rsp.u.getstats.stats.snack_pdus,
Packit Service 646995
Packit Service 646995
		rsp.u.getstats.stats.noprx_pdus,
Packit Service 646995
		rsp.u.getstats.stats.scsirsp_pdus,
Packit Service 646995
		rsp.u.getstats.stats.tmfrsp_pdus,
Packit Service 646995
		rsp.u.getstats.stats.textrsp_pdus,
Packit Service 646995
		rsp.u.getstats.stats.datain_pdus,
Packit Service 646995
		rsp.u.getstats.stats.logoutrsp_pdus,
Packit Service 646995
		rsp.u.getstats.stats.r2t_pdus,
Packit Service 646995
		rsp.u.getstats.stats.async_pdus,
Packit Service 646995
		rsp.u.getstats.stats.rjt_pdus,
Packit Service 646995
Packit Service 646995
		rsp.u.getstats.stats.digest_err,
Packit Service 646995
		rsp.u.getstats.stats.timeout_err);
Packit Service 646995
Packit Service 646995
	if (rsp.u.getstats.stats.custom_length)
Packit Service 646995
		printf( "iSCSI Extended:\n");
Packit Service 646995
Packit Service 646995
	for (i = 0; i < (int)rsp.u.getstats.stats.custom_length; i++) {
Packit Service 646995
		printf("\t%s: %llu\n", rsp.u.getstats.stats.custom[i].desc,
Packit Service 646995
		      (unsigned long long)rsp.u.getstats.stats.custom[i].value);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int add_static_rec(int *found, char *targetname, int tpgt,
Packit Service 646995
			  char *ip, int port, struct iface_rec *iface)
Packit Service 646995
{
Packit Service 646995
	node_rec_t *rec;
Packit Service 646995
	discovery_rec_t *drec;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	rec = calloc(1, sizeof(*rec));
Packit Service 646995
	if (!rec) {
Packit Service 646995
		log_error("Could not allocate memory for node addition");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto done;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	drec = calloc(1, sizeof(*drec));
Packit Service 646995
	if (!drec) {
Packit Service 646995
		log_error("Could not allocate memory for node addition");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto free_rec;
Packit Service 646995
	}
Packit Service 646995
	drec->type = DISCOVERY_TYPE_STATIC;
Packit Service 646995
Packit Service 646995
	idbm_node_setup_from_conf(rec);
Packit Service 646995
	strlcpy(rec->name, targetname, TARGET_NAME_MAXLEN);
Packit Service 646995
	rec->tpgt = tpgt;
Packit Service 646995
	rec->conn[0].port = port;
Packit Service 646995
	strlcpy(rec->conn[0].address, ip, NI_MAXHOST);
Packit Service 646995
Packit Service 646995
	if (iface) {
Packit Service 646995
		rc = iface_conf_read(iface);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not read iface %s. Error %d",
Packit Service 646995
				  iface->name, rc);
Packit Service 646995
			goto free_drec;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		iface_copy(&rec->iface, iface);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = idbm_add_node(rec, drec, 1);
Packit Service 646995
	if (!rc) {
Packit Service 646995
		(*found)++;
Packit Service 646995
		printf("New iSCSI node [%s:" iface_fmt " %s,%d,%d %s] added\n",
Packit Service 646995
			rec->iface.transport_name, iface_str(&rec->iface),
Packit Service 646995
			ip, port, tpgt, targetname);
Packit Service 646995
	}
Packit Service 646995
free_drec:
Packit Service 646995
	free(drec);
Packit Service 646995
free_rec:
Packit Service 646995
	free(rec);
Packit Service 646995
done:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int add_static_portal(int *found, void *data, char *targetname,
Packit Service 646995
			     int tpgt, char *ip, int port,
Packit Service 646995
			     __attribute__((unused))bool ruw_lock)
Packit Service 646995
{
Packit Service 646995
	node_rec_t *rec = data;
Packit Service 646995
Packit Service 646995
	if (strlen(rec->conn[0].address) &&
Packit Service 646995
	    strcmp(rec->conn[0].address, ip))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	if (rec->conn[0].port != -1 && rec->conn[0].port != port)
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	return add_static_rec(found, targetname, tpgt, ip, port,
Packit Service 646995
			      &rec->iface);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int add_static_node(int *found, void *data, char *targetname,
Packit Service 646995
			   __attribute__((unused))bool ruw_lock)
Packit Service 646995
{
Packit Service 646995
	node_rec_t *rec = data;
Packit Service 646995
Packit Service 646995
	if (!strlen(rec->name))
Packit Service 646995
		goto search;
Packit Service 646995
Packit Service 646995
	if (strcmp(rec->name, targetname))
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	if (!strlen(rec->conn[0].address))
Packit Service 646995
		goto search;
Packit Service 646995
Packit Service 646995
	return add_static_rec(found, targetname, rec->tpgt,
Packit Service 646995
			      rec->conn[0].address,
Packit Service 646995
			      rec->conn[0].port, &rec->iface);
Packit Service 646995
search:
Packit Service 646995
	return idbm_for_each_portal(found, data, add_static_portal,
Packit Service 646995
				    targetname, false);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int add_static_recs(struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	int rc, nr_found = 0;
Packit Service 646995
Packit Service 646995
	rc = idbm_for_each_node(&nr_found, rec, add_static_node, false);
Packit Service 646995
	if (rc)
Packit Service 646995
		goto done;
Packit Service 646995
	/* success */
Packit Service 646995
	if (nr_found > 0)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	/* brand new target */
Packit Service 646995
	if (strlen(rec->name) && strlen(rec->conn[0].address)) {
Packit Service 646995
		rc = add_static_rec(&nr_found, rec->name, rec->tpgt,
Packit Service 646995
				    rec->conn[0].address, rec->conn[0].port,
Packit Service 646995
				    &rec->iface);
Packit Service 646995
		if (!rc)
Packit Service 646995
			return 0;
Packit Service 646995
	}
Packit Service 646995
done:
Packit Service 646995
	log_error("Error while adding record: %s", iscsi_err_to_str(rc));
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * start sendtargets discovery process based on the
Packit Service 646995
 * particular config
Packit Service 646995
 */
Packit Service 646995
static int
Packit Service 646995
do_offload_sendtargets(discovery_rec_t *drec, int host_no, int do_login)
Packit Service 646995
{
Packit Service 646995
	drec->type = DISCOVERY_TYPE_OFFLOAD_SENDTARGETS;
Packit Service 646995
	return discovery_offload_sendtargets(host_no, do_login, drec);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int delete_node(__attribute__((unused))void *data,
Packit Service 646995
		       struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	if (iscsi_check_for_running_session(rec)) {
Packit Service 646995
		/*
Packit Service 646995
 		 * We could log out the session for the user, but if
Packit Service 646995
 		 * the session is being used the user may get something
Packit Service 646995
 		 * they were not expecting (FS errors and a read only
Packit Service 646995
 		 * remount).
Packit Service 646995
		 */
Packit Service 646995
		log_error("This command will remove the record [iface: %s, "
Packit Service 646995
			  "target: %s, portal: %s,%d], but a session is "
Packit Service 646995
			  "using it. Logout session then rerun command to "
Packit Service 646995
			  "remove record.", rec->iface.name, rec->name,
Packit Service 646995
			  rec->conn[0].address, rec->conn[0].port);
Packit Service 646995
		return ISCSI_ERR_SESS_EXISTS;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return idbm_delete_node(rec);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int delete_stale_rec(void *data, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct list_head *new_rec_list = data;
Packit Service 646995
	struct node_rec *new_rec;
Packit Service 646995
Packit Service 646995
	list_for_each_entry(new_rec, new_rec_list, list) {
Packit Service 646995
		/*
Packit Service 646995
		 * We could also move this to idbm.c and instead of looping
Packit Service 646995
		 * over every node just loop over disc to node links.
Packit Service 646995
		 */
Packit Service 646995
		if (rec->disc_type != new_rec->disc_type ||
Packit Service 646995
		    rec->disc_port != new_rec->disc_port ||
Packit Service 646995
		    strcmp(rec->disc_address, new_rec->disc_address))
Packit Service 646995
			/*
Packit Service 646995
			 * if we are not from the same discovery source
Packit Service 646995
			 * ignore it
Packit Service 646995
			 */
Packit Service 646995
			return -1;
Packit Service 646995
Packit Service 646995
		if (__iscsi_match_session(rec,
Packit Service 646995
					  new_rec->name,
Packit Service 646995
					  new_rec->conn[0].address,
Packit Service 646995
					  new_rec->conn[0].port,
Packit Service 646995
					  &new_rec->iface,
Packit Service 646995
					  new_rec->session.sid))
Packit Service 646995
			return -1;
Packit Service 646995
	}
Packit Service 646995
	/* if there is a error we can continue on */
Packit Service 646995
	return delete_node(NULL, rec);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
exec_disc_op_on_recs(discovery_rec_t *drec, struct list_head *rec_list,
Packit Service 646995
		     int info_level, int do_login, int op)
Packit Service 646995
{
Packit Service 646995
	int rc = 0, err, found = 0;
Packit Service 646995
	struct node_rec *new_rec, tmp_rec;
Packit Service 646995
Packit Service 646995
	/* clean up node db */
Packit Service 646995
	if (op & OP_DELETE)
Packit Service 646995
		idbm_for_each_rec(&found, rec_list, delete_stale_rec, false);
Packit Service 646995
Packit Service 646995
	if (op & OP_NEW || op & OP_UPDATE) {
Packit Service 646995
		/* now add/update records */
Packit Service 646995
		list_for_each_entry(new_rec, rec_list, list) {
Packit Service 646995
			rc = idbm_add_node(new_rec, drec, op & OP_UPDATE);
Packit Service 646995
			if (rc)
Packit Service 646995
				log_error("Could not add/update "
Packit Service 646995
					  "[%s:" iface_fmt " %s,%d,%d %s]",
Packit Service 646995
					   new_rec->iface.transport_name,
Packit Service 646995
					   iface_str(&new_rec->iface),
Packit Service 646995
					   new_rec->conn[0].address,
Packit Service 646995
					   new_rec->conn[0].port,
Packit Service 646995
					   new_rec->tpgt, new_rec->name);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&tmp_rec, 0, sizeof(node_rec_t));
Packit Service 646995
	list_for_each_entry(new_rec, rec_list, list) {
Packit Service 646995
		switch (info_level) {
Packit Service 646995
		case 0:
Packit Service 646995
		case -1:
Packit Service 646995
			idbm_print_node_flat(NULL, new_rec);
Packit Service 646995
			break;
Packit Service 646995
		case 1:
Packit Service 646995
			idbm_print_node_and_iface_tree(&tmp_rec, new_rec);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!do_login)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	err = iscsi_login_portals(NULL, &found, 1, rec_list,
Packit Service 646995
				  iscsi_login_portal);
Packit Service 646995
	if (err && !rc)
Packit Service 646995
		rc = err;
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
do_software_sendtargets(discovery_rec_t *drec, struct list_head *ifaces,
Packit Service 646995
		        int info_level, int do_login, int op, int sync_drec)
Packit Service 646995
{
Packit Service 646995
	LIST_HEAD(rec_list);
Packit Service 646995
	struct node_rec *rec, *tmp;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * compat: if the user did not pass any op then we do all
Packit Service 646995
	 * ops for them
Packit Service 646995
	 */
Packit Service 646995
	if (!op)
Packit Service 646995
		op = OP_NEW | OP_DELETE | OP_UPDATE;
Packit Service 646995
Packit Service 646995
	drec->type = DISCOVERY_TYPE_SENDTARGETS;
Packit Service 646995
	/*
Packit Service 646995
	 * we will probably want to know how a specific iface and discovery
Packit Service 646995
	 * DB lined up, but for now just put all the targets found from
Packit Service 646995
	 * a discovery portal in one place
Packit Service 646995
	 */
Packit Service 646995
	if ((!(op & OP_NONPERSISTENT)) && sync_drec) {
Packit Service 646995
		rc = idbm_add_discovery(drec);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not add new discovery record.");
Packit Service 646995
			return rc;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = idbm_bind_ifaces_to_nodes(discovery_sendtargets, drec, ifaces,
Packit Service 646995
				       &rec_list);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not perform SendTargets discovery: %s",
Packit Service 646995
			  iscsi_err_to_str(rc));
Packit Service 646995
		return rc;
Packit Service 646995
	} else if (list_empty(&rec_list)) {
Packit Service 646995
		log_error("No portals found");
Packit Service 646995
		return ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = exec_disc_op_on_recs(drec, &rec_list, info_level, do_login, op);
Packit Service 646995
Packit Service 646995
	list_for_each_entry_safe(rec, tmp, &rec_list, list) {
Packit Service 646995
		list_del(&rec->list);
Packit Service 646995
		free(rec);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int do_isns(discovery_rec_t *drec, struct list_head *ifaces,
Packit Service 646995
		   int info_level, int do_login, int op)
Packit Service 646995
{
Packit Service 646995
	LIST_HEAD(rec_list);
Packit Service 646995
	struct node_rec *rec, *tmp;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * compat: if the user did not pass any op then we do all
Packit Service 646995
	 * ops for them
Packit Service 646995
	 */
Packit Service 646995
	if (!op)
Packit Service 646995
		op = OP_NEW | OP_DELETE | OP_UPDATE;
Packit Service 646995
Packit Service 646995
Packit Service 646995
	rc = idbm_bind_ifaces_to_nodes(discovery_isns, drec, ifaces,
Packit Service 646995
				       &rec_list);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not perform iSNS discovery: %s",
Packit Service 646995
			  iscsi_err_to_str(rc));
Packit Service 646995
		return rc;
Packit Service 646995
	} else if (list_empty(&rec_list)) {
Packit Service 646995
		log_error("No portals found");
Packit Service 646995
		return ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = exec_disc_op_on_recs(drec, &rec_list, info_level, do_login, op);
Packit Service 646995
Packit Service 646995
	list_for_each_entry_safe(rec, tmp, &rec_list, list) {
Packit Service 646995
		list_del(&rec->list);
Packit Service 646995
		free(rec);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
do_target_discovery(discovery_rec_t *drec, struct list_head *ifaces,
Packit Service 646995
		    int info_level, int do_login, int op, int sync_drec)
Packit Service 646995
{
Packit Service 646995
Packit Service 646995
	struct iface_rec *tmp, *iface;
Packit Service 646995
	int rc, host_no;
Packit Service 646995
	struct iscsi_transport *t;
Packit Service 646995
Packit Service 646995
	if (list_empty(ifaces)) {
Packit Service 646995
		ifaces = NULL;
Packit Service 646995
		goto sw_discovery;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* we allow users to mix hw and sw iscsi so we have to sort it out */
Packit Service 646995
	list_for_each_entry_safe(iface, tmp, ifaces, list) {
Packit Service 646995
		rc = iface_conf_read(iface);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not read iface info for %s. "
Packit Service 646995
				  "Make sure an iface config with the file "
Packit Service 646995
				  "name and iface.iscsi_ifacename %s is in %s.",
Packit Service 646995
				  iface->name, iface->name, IFACE_CONFIG_DIR);
Packit Service 646995
			list_del(&iface->list);
Packit Service 646995
			free(iface);
Packit Service 646995
			continue;
Packit Service 646995
		}
Packit Service 646995
		/* check for transport name first to make sure it is loaded */
Packit Service 646995
		t = iscsi_sysfs_get_transport_by_name(iface->transport_name);
Packit Service 646995
		if (!t) {
Packit Service 646995
			log_error("Could not load transport %s."
Packit Service 646995
				  "Dropping interface %s.",
Packit Service 646995
				   iface->transport_name, iface->name);
Packit Service 646995
			list_del(&iface->list);
Packit Service 646995
			free(iface);
Packit Service 646995
			continue;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
Packit Service 646995
		if (rc || host_no == -1) {
Packit Service 646995
			log_debug(1, "Could not match iface" iface_fmt " to "
Packit Service 646995
				  "host.", iface_str(iface));
Packit Service 646995
			/* try software iscsi */
Packit Service 646995
			continue;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (drec->type ==  DISCOVERY_TYPE_SENDTARGETS)
Packit Service 646995
			if (t->caps & CAP_SENDTARGETS_OFFLOAD) {
Packit Service 646995
				do_offload_sendtargets(drec, host_no, do_login);
Packit Service 646995
				list_del(&iface->list);
Packit Service 646995
				free(iface);
Packit Service 646995
			}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (list_empty(ifaces))
Packit Service 646995
		return ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
Packit Service 646995
sw_discovery:
Packit Service 646995
	switch (drec->type) {
Packit Service 646995
	case DISCOVERY_TYPE_SENDTARGETS:
Packit Service 646995
		return do_software_sendtargets(drec, ifaces, info_level,
Packit Service 646995
						do_login, op, sync_drec);
Packit Service 646995
	case DISCOVERY_TYPE_ISNS:
Packit Service 646995
		return do_isns(drec, ifaces, info_level, do_login, op);
Packit Service 646995
	default:
Packit Service 646995
		log_debug(1, "Unknown Discovery Type : %d", drec->type);
Packit Service 646995
		return ISCSI_ERR_UNKNOWN_DISCOVERY_TYPE;
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
Packit Service 646995
static int
Packit Service 646995
verify_mode_params(int argc, char **argv, char *allowed, int skip_m)
Packit Service 646995
{
Packit Service 646995
	int ch, longindex;
Packit Service 646995
	int ret = 0;
Packit Service 646995
Packit Service 646995
	optind = 0;
Packit Service 646995
Packit Service 646995
	while ((ch = getopt_long(argc, argv, short_options,
Packit Service 646995
				 long_options, &longindex)) >= 0) {
Packit Service 646995
		if (!strchr(allowed, ch)) {
Packit Service 646995
			if (ch == 'm' && skip_m)
Packit Service 646995
				continue;
Packit Service 646995
			ret = ch;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return ret;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void catch_sigint(__attribute__((unused))int signo) {
Packit Service 646995
	log_warning("caught SIGINT, exiting...");
Packit Service 646995
	exit(1);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int iface_apply_net_config(struct iface_rec *iface, int op)
Packit Service 646995
{
Packit Service 646995
	int rc = ISCSI_ERR;
Packit Service 646995
	uint32_t host_no;
Packit Service 646995
	int param_count;
Packit Service 646995
	int param_used;
Packit Service 646995
	int iface_all = 0;
Packit Service 646995
	int i;
Packit Service 646995
	struct iovec *iovs = NULL;
Packit Service 646995
	struct iovec *iov = NULL;
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	int fd;
Packit Service 646995
Packit Service 646995
	log_debug(8, "Calling iscsid, to apply net config for"
Packit Service 646995
		  "iface.name = %s", iface->name);
Packit Service 646995
Packit Service 646995
	if (op == OP_APPLY_ALL)
Packit Service 646995
		iface_all = 1;
Packit Service 646995
Packit Service 646995
	param_count = iface_get_param_count(iface, iface_all);
Packit Service 646995
	if (!param_count) {
Packit Service 646995
		log_error("Nothing to configure.");
Packit Service 646995
		return ISCSI_SUCCESS;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * TODO: create a nicer interface where the caller does not have
Packit Service 646995
	 * know the packet/hdr details
Packit Service 646995
	 */
Packit Service 646995
Packit Service 646995
	/* +2 for event and nlmsghdr */
Packit Service 646995
	param_count += 2;
Packit Service 646995
	iovs = calloc((param_count * sizeof(struct iovec)),
Packit Service 646995
		       sizeof(char));
Packit Service 646995
	if (!iovs) {
Packit Service 646995
		log_error("Out of Memory.");
Packit Service 646995
		return ISCSI_ERR_NOMEM;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* param_used gives actual number of iovecs used for netconfig */
Packit Service 646995
	param_used = iface_build_net_config(iface, iface_all, iovs);
Packit Service 646995
	if (!param_used) {
Packit Service 646995
		log_error("Build netconfig failed.");
Packit Service 646995
		goto free_buf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_name(iface->transport_name);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Can't find transport.");
Packit Service 646995
		goto free_buf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
Packit Service 646995
	if (host_no == 0) {
Packit Service 646995
		log_error("Can't find host_no.");
Packit Service 646995
		goto free_buf;
Packit Service 646995
	}
Packit Service 646995
	rc = ISCSI_ERR;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		goto free_buf;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = ipc->set_net_config(t->handle, host_no, iovs, param_count);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		log_error("Set net_config failed. errno=%d", errno);
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
free_buf:
Packit Service 646995
	/* start at 2, because 0 is for nlmsghdr and 1 for event */
Packit Service 646995
	iov = iovs + 2;
Packit Service 646995
	for (i = 0; i < param_used; i++, iov++) {
Packit Service 646995
		if (iov->iov_base)
Packit Service 646995
			free(iov->iov_base);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	free(iovs);
Packit Service 646995
	if (rc)
Packit Service 646995
		return ISCSI_ERR;
Packit Service 646995
	return ISCSI_SUCCESS;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int get_host_chap_info(uint32_t host_no)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	struct iscsi_chap_rec *crec = NULL;
Packit Service 646995
	char *req_buf = NULL;
Packit Service 646995
	uint32_t valid_chap_entries;
Packit Service 646995
	uint32_t num_entries;
Packit Service 646995
	uint16_t chap_tbl_idx = 0;
Packit Service 646995
	int rc = 0;
Packit Service 646995
	int fd;
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_hba(host_no);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Could not match hostno %d to "
Packit Service 646995
			  "transport.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto exit_chap_info;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	num_entries = MAX_CHAP_BUF_SZ / sizeof(*crec);
Packit Service 646995
Packit Service 646995
	req_buf = calloc(1, REQ_CHAP_BUF_SZ);
Packit Service 646995
	if (!req_buf) {
Packit Service 646995
		log_error("Could not allocate memory for CHAP request.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto exit_chap_info;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		goto exit_chap_info;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
get_chap:
Packit Service 646995
	memset(req_buf, 0, REQ_CHAP_BUF_SZ);
Packit Service 646995
Packit Service 646995
	rc = ipc->get_chap(t->handle, host_no, chap_tbl_idx, num_entries,
Packit Service 646995
			   req_buf, &valid_chap_entries);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("get_chap_info failed. errno=%d", errno);
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
		goto exit_chap_info;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	crec = (struct iscsi_chap_rec *) (req_buf +
Packit Service 646995
					  sizeof(struct iscsi_uevent));
Packit Service 646995
Packit Service 646995
	if (valid_chap_entries)
Packit Service 646995
		chap_tbl_idx =
Packit Service 646995
		(crec + (valid_chap_entries - 1))->chap_tbl_idx + 1;
Packit Service 646995
Packit Service 646995
	/* print chap info */
Packit Service 646995
	for (uint32_t i = 0; i < valid_chap_entries; i++) {
Packit Service 646995
		idbm_print_host_chap_info(crec);
Packit Service 646995
		crec++;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (valid_chap_entries != num_entries)
Packit Service 646995
		goto exit_chap_info;
Packit Service 646995
	else
Packit Service 646995
		goto get_chap;
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_chap_info:
Packit Service 646995
	if (req_buf)
Packit Service 646995
		free(req_buf);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int fill_host_chap_rec(struct list_head *params,
Packit Service 646995
			      struct iscsi_chap_rec *crec, recinfo_t *cinfo,
Packit Service 646995
			      uint16_t chap_tbl_idx, int type, int *param_count)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	crec->chap_tbl_idx = chap_tbl_idx;
Packit Service 646995
	crec->chap_type = type;
Packit Service 646995
Packit Service 646995
	idbm_recinfo_host_chap(crec, cinfo);
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		rc = idbm_rec_update_param(cinfo, param->name, param->value, 0);
Packit Service 646995
		if (rc)
Packit Service 646995
			break;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!rc)
Packit Service 646995
		*param_count += 3; /* index, type and password_length */
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int verify_host_chap_params(struct list_head *params, int *type,
Packit Service 646995
				   int *param_count)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	int username = -1;
Packit Service 646995
	int password = -1;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		*param_count += 1;
Packit Service 646995
Packit Service 646995
		if (!strcmp(param->name, HOST_AUTH_USERNAME))
Packit Service 646995
			username = CHAP_TYPE_OUT;
Packit Service 646995
		else if (!strcmp(param->name, HOST_AUTH_PASSWORD))
Packit Service 646995
			password = CHAP_TYPE_OUT;
Packit Service 646995
		else if (!strcmp(param->name, HOST_AUTH_USERNAME_IN))
Packit Service 646995
			username = CHAP_TYPE_IN;
Packit Service 646995
		else if (!strcmp(param->name, HOST_AUTH_PASSWORD_IN))
Packit Service 646995
			password = CHAP_TYPE_IN;
Packit Service 646995
		else
Packit Service 646995
			continue;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((username == CHAP_TYPE_OUT) && (password == CHAP_TYPE_OUT)) {
Packit Service 646995
		if (type)
Packit Service 646995
			*type = CHAP_TYPE_OUT;
Packit Service 646995
Packit Service 646995
		rc = ISCSI_SUCCESS;
Packit Service 646995
	} else if ((username == CHAP_TYPE_IN) && (password == CHAP_TYPE_IN)) {
Packit Service 646995
		if (type)
Packit Service 646995
			*type = CHAP_TYPE_IN;
Packit Service 646995
Packit Service 646995
		rc = ISCSI_SUCCESS;
Packit Service 646995
	} else {
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int set_host_chap_info(uint32_t host_no, uint64_t chap_index,
Packit Service 646995
			      struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	struct iscsi_chap_rec crec;
Packit Service 646995
	recinfo_t *chap_info = NULL;
Packit Service 646995
	struct iovec *iovs = NULL;
Packit Service 646995
	struct iovec *iov = NULL;
Packit Service 646995
	int type;
Packit Service 646995
	int param_count = 0;
Packit Service 646995
	int param_used;
Packit Service 646995
	int rc = 0;
Packit Service 646995
	int fd, i = 0;
Packit Service 646995
Packit Service 646995
	if (list_empty(params)) {
Packit Service 646995
		log_error("Chap username/password not provided.");
Packit Service 646995
		goto exit_set_chap;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	chap_info = idbm_recinfo_alloc(MAX_KEYS);
Packit Service 646995
	if (!chap_info) {
Packit Service 646995
		log_error("Out of Memory.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto exit_set_chap;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_hba(host_no);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Could not match hostno %d to transport.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = verify_host_chap_params(params, &type, &param_count);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Invalid username/password pair passed. Unable to determine the type of chap entry");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (param_count > 2) {
Packit Service 646995
		log_error("Only one pair of username/password can be passed.");
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&crec, 0, sizeof(crec));
Packit Service 646995
	rc = fill_host_chap_rec(params, &crec, chap_info, chap_index, type,
Packit Service 646995
				&param_count);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Unable to fill CHAP record");
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* +2 for event and nlmsghdr */
Packit Service 646995
	param_count += 2;
Packit Service 646995
	iovs = calloc((param_count * sizeof(struct iovec)),
Packit Service 646995
		       sizeof(char));
Packit Service 646995
	if (!iovs) {
Packit Service 646995
		log_error("Out of Memory.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* param_used gives actual number of iovecs used for chap */
Packit Service 646995
	param_used = chap_build_config(&crec, iovs);
Packit Service 646995
	if (!param_used) {
Packit Service 646995
		log_error("Build chap config failed.");
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
		goto free_iovec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		goto free_iovec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = ipc->set_chap(t->handle, host_no, iovs, param_count);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("CHAP setting failed");
Packit Service 646995
		if (rc == -EBUSY) {
Packit Service 646995
			rc = ISCSI_ERR_BUSY;
Packit Service 646995
			log_error("CHAP index %d is in use.",
Packit Service 646995
				  crec.chap_tbl_idx);
Packit Service 646995
		} else {
Packit Service 646995
			rc = ISCSI_ERR;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		goto free_iovec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
free_iovec:
Packit Service 646995
	/* start at 2, because 0 is for nlmsghdr and 1 for event */
Packit Service 646995
	iov = iovs + 2;
Packit Service 646995
	for (i = 0; i < param_used; i++, iov++) {
Packit Service 646995
		if (iov->iov_base)
Packit Service 646995
			free(iov->iov_base);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	free(iovs);
Packit Service 646995
Packit Service 646995
free_info_rec:
Packit Service 646995
	if (chap_info)
Packit Service 646995
		free(chap_info);
Packit Service 646995
Packit Service 646995
exit_set_chap:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int delete_host_chap_info(uint32_t host_no, uint16_t chap_tbl_idx)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	if (chap_tbl_idx > MAX_CHAP_ENTRIES) {
Packit Service 646995
		log_error("Invalid chap table index.");
Packit Service 646995
		goto exit_delete_chap;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_hba(host_no);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Could not match hostno %d to "
Packit Service 646995
			  "transport.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto exit_delete_chap;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_delete_chap;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Deleting CHAP index: %d", chap_tbl_idx);
Packit Service 646995
	rc = ipc->delete_chap(t->handle, host_no, chap_tbl_idx);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("CHAP Delete failed.");
Packit Service 646995
		if (rc == -EBUSY) {
Packit Service 646995
			rc = ISCSI_ERR_BUSY;
Packit Service 646995
			log_error("CHAP index %d is in use.", chap_tbl_idx);
Packit Service 646995
		} else
Packit Service 646995
			rc = ISCSI_ERR;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_delete_chap:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_host_chap_op(int op,
Packit Service 646995
			     __attribute__((unused))int info_level,
Packit Service 646995
			     uint32_t host_no,
Packit Service 646995
			     uint64_t chap_index,
Packit Service 646995
			     struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	int rc = ISCSI_ERR_INVAL;
Packit Service 646995
Packit Service 646995
	switch (op) {
Packit Service 646995
	case OP_SHOW:
Packit Service 646995
		rc = get_host_chap_info(host_no);
Packit Service 646995
		break;
Packit Service 646995
	case OP_NEW:
Packit Service 646995
	case OP_UPDATE:
Packit Service 646995
		rc = set_host_chap_info(host_no, chap_index, params);
Packit Service 646995
		break;
Packit Service 646995
	case OP_DELETE:
Packit Service 646995
		rc = delete_host_chap_info(host_no, chap_index);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("Invalid operation.");
Packit Service 646995
		break;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int get_flashnode_info(uint32_t host_no, uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	struct flashnode_rec fnode;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	memset(&fnode, 0, sizeof(fnode));
Packit Service 646995
	rc = iscsi_sysfs_get_flashnode_info(&fnode, host_no, flashnode_idx);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not read info for flashnode %u of host %u, %s",
Packit Service 646995
			  flashnode_idx, host_no, strerror(rc));
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	idbm_print_flashnode_info(&fnode);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int list_flashnodes(__attribute__((unused))int info_level,
Packit Service 646995
			   uint32_t host_no)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	int num_found = 0;
Packit Service 646995
Packit Service 646995
	rc = iscsi_sysfs_for_each_flashnode(NULL, host_no, &num_found,
Packit Service 646995
					    flashnode_info_print_flat);
Packit Service 646995
Packit Service 646995
	if (!num_found) {
Packit Service 646995
		log_error("No flashnodes attached to host %u.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_set_flashnode_params(struct iscsi_transport *t, uint32_t host_no,
Packit Service 646995
			       uint32_t flashnode_idx, struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	struct flashnode_rec fnode;
Packit Service 646995
	recinfo_t *flashnode_info;
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	struct iovec *iovs = NULL;
Packit Service 646995
	struct iovec *iov = NULL;
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
	int param_count = 0;
Packit Service 646995
	int param_used = 0;
Packit Service 646995
	int i;
Packit Service 646995
Packit Service 646995
	flashnode_info = idbm_recinfo_alloc(MAX_KEYS);
Packit Service 646995
	if (!flashnode_info) {
Packit Service 646995
		log_error("Out of Memory.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&fnode, 0, sizeof(fnode));
Packit Service 646995
	rc = iscsi_sysfs_get_flashnode_info(&fnode, host_no, flashnode_idx);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not read info for flashnode %u, %s",
Packit Service 646995
			  flashnode_idx, strerror(rc));
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	idbm_recinfo_flashnode(&fnode, flashnode_info);
Packit Service 646995
Packit Service 646995
	i = 0;
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		param_count++;
Packit Service 646995
		rc = idbm_verify_param(flashnode_info, param->name);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		rc = idbm_rec_update_param(flashnode_info, param->name,
Packit Service 646995
					   param->value, 0);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* +2 for event and nlmsghdr */
Packit Service 646995
	param_count += 2;
Packit Service 646995
	iovs = calloc((param_count * sizeof(struct iovec)),
Packit Service 646995
		       sizeof(char));
Packit Service 646995
	if (!iovs) {
Packit Service 646995
		log_error("Out of Memory.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto free_info_rec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* param_used gives actual number of iovecs used for flashnode */
Packit Service 646995
	param_used = flashnode_build_config(params, &fnode, iovs);
Packit Service 646995
	if (!param_used) {
Packit Service 646995
		log_error("Build flashnode config failed.");
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
		goto free_iovec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto free_iovec;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Update flashnode %u.", flashnode_idx);
Packit Service 646995
	rc = ipc->set_flash_node_params(t->handle, host_no, flashnode_idx,
Packit Service 646995
					iovs, param_count);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
free_iovec:
Packit Service 646995
	/* start at 2, because 0 is for nlmsghdr and 1 for event */
Packit Service 646995
	iov = iovs + 2;
Packit Service 646995
	for (i = 0; i < param_used; i++, iov++) {
Packit Service 646995
		if (iov->iov_base)
Packit Service 646995
			free(iov->iov_base);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	free(iovs);
Packit Service 646995
Packit Service 646995
free_info_rec:
Packit Service 646995
	if (flashnode_info)
Packit Service 646995
		free(flashnode_info);
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_new_flashnode(struct iscsi_transport *t, uint32_t host_no, char *val,
Packit Service 646995
			uint32_t *flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_new_flashnode;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Create new flashnode for host %u.", host_no);
Packit Service 646995
	rc = ipc->new_flash_node(t->handle, host_no, val, flashnode_idx);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_new_flashnode:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_del_flashnode(struct iscsi_transport *t, uint32_t host_no,
Packit Service 646995
			uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_del_flashnode;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Delete flashnode %u.", flashnode_idx);
Packit Service 646995
	rc = ipc->del_flash_node(t->handle, host_no, flashnode_idx);
Packit Service 646995
	if (rc < 0)
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_del_flashnode:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_login_flashnode(struct iscsi_transport *t, uint32_t host_no,
Packit Service 646995
			  uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_login_flashnode;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Login to flashnode %u.", flashnode_idx);
Packit Service 646995
	rc = ipc->login_flash_node(t->handle, host_no, flashnode_idx);
Packit Service 646995
	if (rc == -EPERM)
Packit Service 646995
		rc = ISCSI_ERR_SESS_EXISTS;
Packit Service 646995
	else if (rc < 0)
Packit Service 646995
		rc = ISCSI_ERR_LOGIN;
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_login_flashnode:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_logout_flashnode(struct iscsi_transport *t, uint32_t host_no,
Packit Service 646995
			   uint32_t flashnode_idx)
Packit Service 646995
{
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_logout;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Logout flashnode %u.", flashnode_idx);
Packit Service 646995
	rc = ipc->logout_flash_node(t->handle, host_no, flashnode_idx);
Packit Service 646995
	if (rc == -ESRCH)
Packit Service 646995
		rc = ISCSI_ERR_SESS_NOT_FOUND;
Packit Service 646995
	else if (rc < 0)
Packit Service 646995
		rc = ISCSI_ERR_LOGOUT;
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_logout:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int iscsi_check_session_use_count(uint32_t sid) {
Packit Service 646995
	char *config_file;
Packit Service 646995
	char *safe_logout;
Packit Service 646995
Packit Service 646995
	config_file = get_config_file();
Packit Service 646995
	if (!config_file) {
Packit Service 646995
		log_error("Could not get config file from iscsid");
Packit Service 646995
		return 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	safe_logout = cfg_get_string_param(config_file, "iscsid.safe_logout");
Packit Service 646995
	if (!safe_logout || strcmp(safe_logout, "Yes"))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	return session_in_use(sid);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_logout_flashnode_sid(struct iscsi_transport *t, uint32_t host_no,
Packit Service 646995
			       uint32_t sid)
Packit Service 646995
{
Packit Service 646995
	int fd, rc = 0;
Packit Service 646995
Packit Service 646995
	if (iscsi_check_session_use_count(sid)) {
Packit Service 646995
		log_error("Session is actively in use for mounted storage, "
Packit Service 646995
			  "and iscsid.safe_logout is configured.");
Packit Service 646995
		return ISCSI_ERR_BUSY;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		goto exit_logout_sid;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_info("Logout sid %u.", sid);
Packit Service 646995
	rc = ipc->logout_flash_node_sid(t->handle, host_no, sid);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("Logout of sid %u failed.", sid);
Packit Service 646995
		rc = ISCSI_ERR_LOGOUT;
Packit Service 646995
	} else {
Packit Service 646995
		log_info("Logout of sid %u successful.", sid);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_logout_sid:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_flashnode_op(int op, int info_level, uint32_t host_no,
Packit Service 646995
			     uint64_t fnode_idx, int type,
Packit Service 646995
			     struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	int rc = ISCSI_SUCCESS;
Packit Service 646995
	char *portal_type;
Packit Service 646995
	uint32_t flashnode_idx;
Packit Service 646995
Packit Service 646995
	if (op != OP_SHOW && op != OP_NOOP && op != OP_NEW &&
Packit Service 646995
	    fnode_idx > MAX_FLASHNODE_IDX) {
Packit Service 646995
		log_error("Invalid flashnode index");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto exit_flashnode_op;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	flashnode_idx = (uint32_t)fnode_idx;
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_hba(host_no);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Could not match hostno %u to transport.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto exit_flashnode_op;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	switch (op) {
Packit Service 646995
	case OP_NOOP:
Packit Service 646995
	case OP_SHOW:
Packit Service 646995
		if (fnode_idx > MAX_FLASHNODE_IDX)
Packit Service 646995
			rc = list_flashnodes(info_level, host_no);
Packit Service 646995
		else
Packit Service 646995
			rc = get_flashnode_info(host_no, flashnode_idx);
Packit Service 646995
		break;
Packit Service 646995
	case OP_NEW:
Packit Service 646995
		if (type == IPV4) {
Packit Service 646995
			portal_type = "ipv4";
Packit Service 646995
		} else if (type == IPV6) {
Packit Service 646995
			portal_type = "ipv6";
Packit Service 646995
		} else {
Packit Service 646995
			log_error("Invalid type mentioned for flashnode");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto exit_flashnode_op;
Packit Service 646995
		}
Packit Service 646995
		rc = iscsi_new_flashnode(t, host_no, portal_type,
Packit Service 646995
					 &flashnode_idx);
Packit Service 646995
		if (!rc)
Packit Service 646995
			log_info("New flashnode for host %u added at index %u.",
Packit Service 646995
				 host_no, flashnode_idx);
Packit Service 646995
		else
Packit Service 646995
			log_error("Creation of flashnode for host %u failed.",
Packit Service 646995
				  host_no);
Packit Service 646995
		break;
Packit Service 646995
	case OP_DELETE:
Packit Service 646995
		rc = iscsi_del_flashnode(t, host_no, flashnode_idx);
Packit Service 646995
		if (!rc)
Packit Service 646995
			log_info("Flashnode %u of host %u deleted.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else
Packit Service 646995
			log_error("Deletion of flashnode %u of host %u failed.",
Packit Service 646995
				  flashnode_idx, host_no);
Packit Service 646995
		break;
Packit Service 646995
	case OP_UPDATE:
Packit Service 646995
		rc = iscsi_set_flashnode_params(t, host_no, flashnode_idx,
Packit Service 646995
						params);
Packit Service 646995
		if (!rc)
Packit Service 646995
			log_info("Update for flashnode %u of host %u successful.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else
Packit Service 646995
			log_error("Update for flashnode %u of host %u failed.",
Packit Service 646995
				  flashnode_idx, host_no);
Packit Service 646995
		break;
Packit Service 646995
	case OP_LOGIN:
Packit Service 646995
		rc = iscsi_login_flashnode(t, host_no, flashnode_idx);
Packit Service 646995
		if (!rc)
Packit Service 646995
			log_info("Login to flashnode %u of host %u successful.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else if (rc == ISCSI_ERR_SESS_EXISTS)
Packit Service 646995
			log_info("Flashnode %u of host %u already logged in.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else
Packit Service 646995
			log_error("Login to flashnode %u of host %u failed.",
Packit Service 646995
				  flashnode_idx, host_no);
Packit Service 646995
		break;
Packit Service 646995
	case OP_LOGOUT:
Packit Service 646995
		rc = iscsi_logout_flashnode(t, host_no, flashnode_idx);
Packit Service 646995
		if (!rc)
Packit Service 646995
			log_info("Logout of flashnode %u of host %u successful.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else if (rc == ISCSI_ERR_SESS_NOT_FOUND)
Packit Service 646995
			log_info("Flashnode %u of host %u not logged in.",
Packit Service 646995
				 flashnode_idx, host_no);
Packit Service 646995
		else
Packit Service 646995
			log_error("Logout of flashnode %u of host %u failed.",
Packit Service 646995
				  flashnode_idx, host_no);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("Invalid operation");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		break;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
exit_flashnode_op:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void print_host_stats(struct iscsi_offload_host_stats *host_stats)
Packit Service 646995
{
Packit Service 646995
	/* MAC */
Packit Service 646995
	printf("Host Statistics:\n"
Packit Service 646995
	       "\tmactx_frames: %lld\n"
Packit Service 646995
	       "\tmactx_bytes: %lld\n"
Packit Service 646995
	       "\tmactx_multicast_frames: %lld\n"
Packit Service 646995
	       "\tmactx_broadcast_frames: %lld\n"
Packit Service 646995
	       "\tmactx_pause_frames: %lld\n"
Packit Service 646995
	       "\tmactx_control_frames: %lld\n"
Packit Service 646995
	       "\tmactx_deferral: %lld\n"
Packit Service 646995
	       "\tmactx_excess_deferral: %lld\n"
Packit Service 646995
	       "\tmactx_late_collision: %lld\n"
Packit Service 646995
	       "\tmactx_abort: %lld\n"
Packit Service 646995
	       "\tmactx_single_collision: %lld\n"
Packit Service 646995
	       "\tmactx_multiple_collision: %lld\n"
Packit Service 646995
	       "\tmactx_collision: %lld\n"
Packit Service 646995
	       "\tmactx_frames_dropped: %lld\n"
Packit Service 646995
	       "\tmactx_jumbo_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_bytes: %lld\n"
Packit Service 646995
	       "\tmacrx_unknown_control_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_pause_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_control_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_dribble: %lld\n"
Packit Service 646995
	       "\tmacrx_frame_length_error: %lld\n"
Packit Service 646995
	       "\tmacrx_jabber: %lld\n"
Packit Service 646995
	       "\tmacrx_carrier_sense_error: %lld\n"
Packit Service 646995
	       "\tmacrx_frame_discarded: %lld\n"
Packit Service 646995
	       "\tmacrx_frames_dropped: %lld\n"
Packit Service 646995
	       "\tmac_crc_error: %lld\n"
Packit Service 646995
	       "\tmac_encoding_error: %lld\n"
Packit Service 646995
	       "\tmacrx_length_error_large: %lld\n"
Packit Service 646995
	       "\tmacrx_length_error_small: %lld\n"
Packit Service 646995
	       "\tmacrx_multicast_frames: %lld\n"
Packit Service 646995
	       "\tmacrx_broadcast_frames: %lld\n"
Packit Service 646995
	       /* IP */
Packit Service 646995
	       "\tiptx_packets: %lld\n"
Packit Service 646995
	       "\tiptx_bytes: %lld\n"
Packit Service 646995
	       "\tiptx_fragments: %lld\n"
Packit Service 646995
	       "\tiprx_packets: %lld\n"
Packit Service 646995
	       "\tiprx_bytes: %lld\n"
Packit Service 646995
	       "\tiprx_fragments: %lld\n"
Packit Service 646995
	       "\tip_datagram_reassembly: %lld\n"
Packit Service 646995
	       "\tip_invalid_address_error: %lld\n"
Packit Service 646995
	       "\tip_error_packets: %lld\n"
Packit Service 646995
	       "\tip_fragrx_overlap: %lld\n"
Packit Service 646995
	       "\tip_fragrx_outoforder: %lld\n"
Packit Service 646995
	       "\tip_datagram_reassembly_timeout: %lld\n"
Packit Service 646995
	       "\tipv6tx_packets: %lld\n"
Packit Service 646995
	       "\tipv6tx_bytes: %lld\n"
Packit Service 646995
	       "\tipv6tx_fragments: %lld\n"
Packit Service 646995
	       "\tipv6rx_packets: %lld\n"
Packit Service 646995
	       "\tipv6rx_bytes: %lld\n"
Packit Service 646995
	       "\tipv6rx_fragments: %lld\n"
Packit Service 646995
	       "\tipv6_datagram_reassembly: %lld\n"
Packit Service 646995
	       "\tipv6_invalid_address_error: %lld\n"
Packit Service 646995
	       "\tipv6_error_packets: %lld\n"
Packit Service 646995
	       "\tipv6_fragrx_overlap: %lld\n"
Packit Service 646995
	       "\tipv6_fragrx_outoforder: %lld\n"
Packit Service 646995
	       "\tipv6_datagram_reassembly_timeout: %lld\n"
Packit Service 646995
	       /* TCP */
Packit Service 646995
	       "\ttcptx_segments: %lld\n"
Packit Service 646995
	       "\ttcptx_bytes: %lld\n"
Packit Service 646995
	       "\ttcprx_segments: %lld\n"
Packit Service 646995
	       "\ttcprx_byte: %lld\n"
Packit Service 646995
	       "\ttcp_duplicate_ack_retx: %lld\n"
Packit Service 646995
	       "\ttcp_retx_timer_expired: %lld\n"
Packit Service 646995
	       "\ttcprx_duplicate_ack: %lld\n"
Packit Service 646995
	       "\ttcprx_pure_ackr: %lld\n"
Packit Service 646995
	       "\ttcptx_delayed_ack: %lld\n"
Packit Service 646995
	       "\ttcptx_pure_ack: %lld\n"
Packit Service 646995
	       "\ttcprx_segment_error: %lld\n"
Packit Service 646995
	       "\ttcprx_segment_outoforder: %lld\n"
Packit Service 646995
	       "\ttcprx_window_probe: %lld\n"
Packit Service 646995
	       "\ttcprx_window_update: %lld\n"
Packit Service 646995
	       "\ttcptx_window_probe_persist: %lld\n"
Packit Service 646995
	       /* ECC */
Packit Service 646995
	       "\tecc_error_correction: %lld\n"
Packit Service 646995
	       /* iSCSI */
Packit Service 646995
	       "\tiscsi_pdu_tx: %lld\n"
Packit Service 646995
	       "\tiscsi_data_bytes_tx: %lld\n"
Packit Service 646995
	       "\tiscsi_pdu_rx: %lld\n"
Packit Service 646995
	       "\tiscsi_data_bytes_rx: %lld\n"
Packit Service 646995
	       "\tiscsi_io_completed: %lld\n"
Packit Service 646995
	       "\tiscsi_unexpected_io_rx: %lld\n"
Packit Service 646995
	       "\tiscsi_format_error: %lld\n"
Packit Service 646995
	       "\tiscsi_hdr_digest_error: %lld\n"
Packit Service 646995
	       "\tiscsi_data_digest_error: %lld\n"
Packit Service 646995
	       "\tiscsi_sequence_error: %lld\n",
Packit Service 646995
	       /* MAC */
Packit Service 646995
	       (unsigned long long)host_stats->mactx_frames,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_multicast_frames,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_broadcast_frames,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_pause_frames,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_control_frames,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_deferral,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_excess_deferral,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_late_collision,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_abort,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_single_collision,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_multiple_collision,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_collision,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_frames_dropped,
Packit Service 646995
	       (unsigned long long)host_stats->mactx_jumbo_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_unknown_control_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_pause_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_control_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_dribble,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_frame_length_error,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_jabber,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_carrier_sense_error,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_frame_discarded,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_frames_dropped,
Packit Service 646995
	       (unsigned long long)host_stats->mac_crc_error,
Packit Service 646995
	       (unsigned long long)host_stats->mac_encoding_error,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_length_error_large,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_length_error_small,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_multicast_frames,
Packit Service 646995
	       (unsigned long long)host_stats->macrx_broadcast_frames,
Packit Service 646995
	       /* IP */
Packit Service 646995
	       (unsigned long long)host_stats->iptx_packets,
Packit Service 646995
	       (unsigned long long)host_stats->iptx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->iptx_fragments,
Packit Service 646995
	       (unsigned long long)host_stats->iprx_packets,
Packit Service 646995
	       (unsigned long long)host_stats->iprx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->iprx_fragments,
Packit Service 646995
	       (unsigned long long)host_stats->ip_datagram_reassembly,
Packit Service 646995
	       (unsigned long long)host_stats->ip_invalid_address_error,
Packit Service 646995
	       (unsigned long long)host_stats->ip_error_packets,
Packit Service 646995
	       (unsigned long long)host_stats->ip_fragrx_overlap,
Packit Service 646995
	       (unsigned long long)host_stats->ip_fragrx_outoforder,
Packit Service 646995
	       (unsigned long long)host_stats->ip_datagram_reassembly_timeout,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6tx_packets,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6tx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6tx_fragments,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6rx_packets,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6rx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6rx_fragments,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_datagram_reassembly,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_invalid_address_error,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_error_packets,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_fragrx_overlap,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_fragrx_outoforder,
Packit Service 646995
	       (unsigned long long)host_stats->ipv6_datagram_reassembly_timeout,
Packit Service 646995
	       /* TCP */
Packit Service 646995
	       (unsigned long long)host_stats->tcptx_segments,
Packit Service 646995
	       (unsigned long long)host_stats->tcptx_bytes,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_segments,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_byte,
Packit Service 646995
	       (unsigned long long)host_stats->tcp_duplicate_ack_retx,
Packit Service 646995
	       (unsigned long long)host_stats->tcp_retx_timer_expired,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_duplicate_ack,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_pure_ackr,
Packit Service 646995
	       (unsigned long long)host_stats->tcptx_delayed_ack,
Packit Service 646995
	       (unsigned long long)host_stats->tcptx_pure_ack,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_segment_error,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_segment_outoforder,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_window_probe,
Packit Service 646995
	       (unsigned long long)host_stats->tcprx_window_update,
Packit Service 646995
	       (unsigned long long)host_stats->tcptx_window_probe_persist,
Packit Service 646995
	       /* ECC */
Packit Service 646995
	       (unsigned long long)host_stats->ecc_error_correction,
Packit Service 646995
	       /* iSCSI */
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_pdu_tx,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_data_bytes_tx,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_pdu_rx,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_data_bytes_rx,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_io_completed,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_unexpected_io_rx,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_format_error,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_hdr_digest_error,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_data_digest_error,
Packit Service 646995
	       (unsigned long long)host_stats->iscsi_sequence_error);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_host_stats_op(__attribute__((unused))int op,
Packit Service 646995
			      __attribute__((unused))int info_level,
Packit Service 646995
			      uint32_t host_no)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	char *req_buf = NULL;
Packit Service 646995
	int rc = ISCSI_SUCCESS;
Packit Service 646995
	int fd = 0, buf_size = 0;
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_hba(host_no);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Could not match hostno %u to transport.", host_no);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto exit_host_stats;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	buf_size = sizeof(struct iscsi_offload_host_stats) +
Packit Service 646995
		   sizeof(struct iscsi_uevent);
Packit Service 646995
	req_buf = calloc(1, buf_size);
Packit Service 646995
	if (!req_buf) {
Packit Service 646995
		log_error("Could not allocate memory for host stats request.");
Packit Service 646995
		rc = ISCSI_ERR_NOMEM;
Packit Service 646995
		goto exit_host_stats;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fd = ipc->ctldev_open();
Packit Service 646995
	if (fd < 0) {
Packit Service 646995
		rc = ISCSI_ERR_INTERNAL;
Packit Service 646995
		log_error("Netlink open failed.");
Packit Service 646995
		goto exit_host_stats;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = ipc->get_host_stats(t->handle, host_no, req_buf);
Packit Service 646995
	if (rc < 0) {
Packit Service 646995
		log_error("get_host_stats failed. errno=%d", errno);
Packit Service 646995
		rc = ISCSI_ERR;
Packit Service 646995
		goto exit_host_stats;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	print_host_stats((struct iscsi_offload_host_stats *)(req_buf +
Packit Service 646995
			 sizeof(struct iscsi_uevent)));
Packit Service 646995
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
Packit Service 646995
exit_host_stats:
Packit Service 646995
	free(req_buf);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int verify_iface_params(struct list_head *params, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		if (!strcmp(param->name, IFACE_ISCSINAME)) {
Packit Service 646995
			log_error("Can not update "
Packit Service 646995
				  "iface.iscsi_ifacename. Delete it, "
Packit Service 646995
				  "and then create a new one.");
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (iface_is_bound_by_hwaddr(&rec->iface) &&
Packit Service 646995
		    !strcmp(param->name, IFACE_NETNAME)) {
Packit Service 646995
			log_error("Can not update interface binding "
Packit Service 646995
				  "from hwaddress to net_ifacename. "
Packit Service 646995
				  "You must delete the interface and "
Packit Service 646995
				  "create a new one");
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (iface_is_bound_by_netdev(&rec->iface) &&
Packit Service 646995
		    !strcmp(param->name, IFACE_HWADDR)) {
Packit Service 646995
			log_error("Can not update interface binding "
Packit Service 646995
				  "from net_ifacename to hwaddress. "
Packit Service 646995
				  "You must delete the interface and "
Packit Service 646995
				  "create a new one");
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void _print_iface_tree(struct iscsi_node **nodes, uint32_t node_count,
Packit Service 646995
			      const char *iface_name,
Packit Service 646995
			      struct iscsi_node **matched_nodes)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_node *node = NULL;
Packit Service 646995
	uint32_t matched_node_count = 0;
Packit Service 646995
	uint32_t i = 0;
Packit Service 646995
Packit Service 646995
	for (i = 0; i < node_count; ++i) {
Packit Service 646995
		node = nodes[i];
Packit Service 646995
		if (strcmp(iface_name, iscsi_node_iface_name_get(node))
Packit Service 646995
		    == 0)
Packit Service 646995
			matched_nodes[matched_node_count++] = node;
Packit Service 646995
	}
Packit Service 646995
	printf("Iface: %s\n", iface_name);
Packit Service 646995
	print_nodes_tree(matched_nodes, matched_node_count, _PRINT_MODE_IFACE);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int print_iface_tree(struct iscsi_context *ctx,
Packit Service 646995
			     const char *iface_name)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
	struct iscsi_node **nodes = NULL;
Packit Service 646995
	struct iscsi_node **matched_nodes = NULL;
Packit Service 646995
	uint32_t node_count = 0;
Packit Service 646995
	struct iscsi_iface *iface = NULL;
Packit Service 646995
	struct iscsi_iface **ifaces = NULL;
Packit Service 646995
	uint32_t iface_count = 0;
Packit Service 646995
	uint32_t i = 0;
Packit Service 646995
Packit Service 646995
	_good(iscsi_nodes_get(ctx, &nodes, &node_count),
Packit Service 646995
	      rc, out);
Packit Service 646995
	if (node_count == 0)
Packit Service 646995
		goto out;
Packit Service 646995
	matched_nodes = calloc(node_count, sizeof(struct iscsi_node *));
Packit Service 646995
	if (matched_nodes == NULL) {
Packit Service 646995
		log_error("No memory");
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (iface_name != NULL) {
Packit Service 646995
		// Just make sure specified iface exists
Packit Service 646995
		_good(iscsi_iface_get(ctx, iface_name, &iface), rc, out);
Packit Service 646995
		_print_iface_tree(nodes, node_count, iface_name,
Packit Service 646995
				  matched_nodes);
Packit Service 646995
	} else {
Packit Service 646995
		_good(iscsi_ifaces_get(ctx, &ifaces, &iface_count),
Packit Service 646995
		      rc, out);
Packit Service 646995
		for (i = 0; i < iface_count; ++i)
Packit Service 646995
			_print_iface_tree(nodes, node_count,
Packit Service 646995
					  iscsi_iface_name_get(ifaces[i]),
Packit Service 646995
					  matched_nodes);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
out:
Packit Service 646995
	free(matched_nodes);
Packit Service 646995
	iscsi_ifaces_free(ifaces, iface_count);
Packit Service 646995
	iscsi_iface_free(iface);
Packit Service 646995
	iscsi_nodes_free(nodes, node_count);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int iface_param_update(struct iface_rec *iface, struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	struct node_rec *rec;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
Packit Service 646995
	if (!rec) {
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto update_fail;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (iscsi_check_for_running_session(rec))
Packit Service 646995
		log_warning("Updating iface while iscsi sessions "
Packit Service 646995
			    "are using it. You must logout the running "
Packit Service 646995
			    "sessions then log back in for the "
Packit Service 646995
			    "new settings to take affect.");
Packit Service 646995
Packit Service 646995
	rc = verify_iface_params(params, rec);
Packit Service 646995
	if (rc)
Packit Service 646995
		goto update_fail;
Packit Service 646995
Packit Service 646995
	rc = iface_conf_update(params, &rec->iface);
Packit Service 646995
	if (rc)
Packit Service 646995
		goto update_fail;
Packit Service 646995
Packit Service 646995
	rc = __for_each_matched_rec(0, rec, params, idbm_node_set_param);
Packit Service 646995
	if (rc == ISCSI_ERR_NO_OBJS_FOUND)
Packit Service 646995
		rc = 0;
Packit Service 646995
	else if (rc)
Packit Service 646995
		goto update_fail;
Packit Service 646995
Packit Service 646995
	printf("%s updated.\n", iface->name);
Packit Service 646995
	free(rec);
Packit Service 646995
	return rc;
Packit Service 646995
Packit Service 646995
update_fail:
Packit Service 646995
	log_error("Could not update iface %s: %s",
Packit Service 646995
		  iface->name, iscsi_err_to_str(rc));
Packit Service 646995
	free(rec);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
struct iface_param_sync {
Packit Service 646995
	struct iface_rec *primary;
Packit Service 646995
	struct list_head *params;
Packit Service 646995
	int count;
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static int update_sync_params(void *data, struct iface_rec *iface)
Packit Service 646995
{
Packit Service 646995
	struct iface_param_sync *iface_params = data;
Packit Service 646995
	struct iface_rec *primary = iface_params->primary;
Packit Service 646995
	struct list_head *params = iface_params->params;
Packit Service 646995
Packit Service 646995
	if ((strcmp(primary->transport_name, iface->transport_name)) ||
Packit Service 646995
	    (strcmp(primary->hwaddress, iface->hwaddress)) ||
Packit Service 646995
	    (primary->iface_num != iface->iface_num))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	return iface_param_update(iface, params);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int split_vlan_params(struct list_head *params, struct list_head *vlan_params)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param, *tmp;
Packit Service 646995
Packit Service 646995
	list_for_each_entry_safe(param, tmp, params, list) {
Packit Service 646995
		if (!strncmp(param->name, "iface.vlan", 10)) {
Packit Service 646995
			list_move_tail(&param->list, vlan_params);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static inline void list_splice_tail(struct list_head *list, struct list_head *head)
Packit Service 646995
{
Packit Service 646995
	list->prev->next = head;
Packit Service 646995
	list->next->prev = head->prev;
Packit Service 646995
	head->prev->next = list->next;
Packit Service 646995
	head->prev = list->prev;
Packit Service 646995
	INIT_LIST_HEAD(list);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/* TODO: merge iter helpers and clean them up, so we can use them here */
Packit Service 646995
static int exec_iface_op(struct iscsi_context *ctx,
Packit Service 646995
			 int op,
Packit Service 646995
			 __attribute__((unused))int do_show,
Packit Service 646995
			 int info_level,
Packit Service 646995
			 struct iface_rec *iface,
Packit Service 646995
			 uint64_t host_no,
Packit Service 646995
			 struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	struct host_info hinfo;
Packit Service 646995
	struct node_rec *rec = NULL;
Packit Service 646995
	int rc = 0;
Packit Service 646995
	struct iscsi_iface **ifaces = NULL;
Packit Service 646995
	struct iscsi_iface *iface_info = NULL;
Packit Service 646995
	uint32_t iface_count = 0;
Packit Service 646995
	uint32_t i = 0;
Packit Service 646995
Packit Service 646995
	LIST_HEAD(vlan_params);
Packit Service 646995
	struct iscsi_transport *t;
Packit Service 646995
	switch (op) {
Packit Service 646995
	case OP_NEW:
Packit Service 646995
		if (!iface) {
Packit Service 646995
			log_error("Could not add interface. No interface "
Packit Service 646995
				  "passed in.");
Packit Service 646995
			return EINVAL;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 0);
Packit Service 646995
		if (rec && iscsi_check_for_running_session(rec)) {
Packit Service 646995
			rc = ISCSI_ERR_SESS_EXISTS;
Packit Service 646995
			goto new_fail;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		iface_setup_defaults(iface);
Packit Service 646995
		rc = iface_conf_write(iface);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto new_fail;
Packit Service 646995
		printf("New interface %s added\n", iface->name);
Packit Service 646995
		break;
Packit Service 646995
new_fail:
Packit Service 646995
		log_error("Could not create new interface %s.", iface->name);
Packit Service 646995
		break;
Packit Service 646995
	case OP_DELETE:
Packit Service 646995
		if (!iface) {
Packit Service 646995
			log_error("Could not delete interface. No interface "
Packit Service 646995
				  "passed in.");
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
Packit Service 646995
		if (!rec) {
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto delete_fail;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		/* logout and delete records using it first */
Packit Service 646995
		rc = __for_each_matched_rec(0, rec, NULL, delete_node);
Packit Service 646995
		if (rc && rc != ISCSI_ERR_NO_OBJS_FOUND)
Packit Service 646995
			goto delete_fail;
Packit Service 646995
Packit Service 646995
		rc = iface_conf_delete(iface);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto delete_fail;
Packit Service 646995
Packit Service 646995
		printf("%s unbound and deleted.\n", iface->name);
Packit Service 646995
		break;
Packit Service 646995
delete_fail:
Packit Service 646995
		log_error("Could not delete iface %s: %s", iface->name,
Packit Service 646995
			  iscsi_err_to_str(rc));
Packit Service 646995
		break;
Packit Service 646995
	case OP_UPDATE:
Packit Service 646995
		if (!iface || list_empty(params)) {
Packit Service 646995
			log_error("Update requires name, value, and iface.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
Packit Service 646995
		if (!rec) {
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
Packit Service 646995
		if (!t) {
Packit Service 646995
			log_error("Cound not locate transport for iface %s", iface->name);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		if (t->template->sync_vlan_settings) {
Packit Service 646995
			/* sync shared vlan settings across ifaces */
Packit Service 646995
			int nr_found = 0;
Packit Service 646995
			struct iface_param_sync sync_params = {
Packit Service 646995
				.primary = &rec->iface,
Packit Service 646995
				.params = &vlan_params,
Packit Service 646995
				.count = 0,
Packit Service 646995
			};
Packit Service 646995
			split_vlan_params(params, &vlan_params);
Packit Service 646995
			iface_for_each_iface(&sync_params, 1, &nr_found, update_sync_params);
Packit Service 646995
		}
Packit Service 646995
		iface_param_update(&rec->iface, params);
Packit Service 646995
		list_splice_tail(&vlan_params, params);
Packit Service 646995
		break;
Packit Service 646995
	case OP_APPLY:
Packit Service 646995
		if (!iface) {
Packit Service 646995
			log_error("Apply requires iface.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		rc = iface_conf_read(iface);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not read iface %s (%d).",
Packit Service 646995
				  iface->name, rc);
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc = iface_apply_net_config(iface, op);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not apply net configuration: %s",
Packit Service 646995
				  iscsi_err_to_str(rc));
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		printf("%s applied.\n", iface->name);
Packit Service 646995
		break;
Packit Service 646995
	case OP_APPLY_ALL:
Packit Service 646995
		if (host_no > MAX_HOST_NO) {
Packit Service 646995
			log_error("Applyall requires a valid host number or MAC"
Packit Service 646995
				  " passed in with the --host argument.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		/*
Packit Service 646995
		 * Need to get other iface info like transport.
Packit Service 646995
		 */
Packit Service 646995
		memset(&hinfo, 0, sizeof(struct host_info));
Packit Service 646995
		hinfo.host_no = host_no;
Packit Service 646995
		if (iscsi_sysfs_get_hostinfo_by_host_no(&hinfo)) {
Packit Service 646995
			log_error("Could not match host%" PRIu64 " to ifaces.",
Packit Service 646995
				  host_no);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		rc = iface_apply_net_config(&hinfo.iface, op);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not apply net configuration: %s",
Packit Service 646995
				  iscsi_err_to_str(rc));
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		printf("Applied settings to ifaces attached to host%" PRIu64 ".\n",
Packit Service 646995
		       host_no);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		if ((op != OP_NOOP) && (op != OP_SHOW)) {
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
		switch (info_level) {
Packit Service 646995
		case 0:
Packit Service 646995
		case -1:
Packit Service 646995
			if (iface == NULL) {
Packit Service 646995
				_good(iscsi_ifaces_get(ctx, &ifaces,
Packit Service 646995
						       &iface_count),
Packit Service 646995
				      rc, out);
Packit Service 646995
				if (iface_count == 0) {
Packit Service 646995
					log_error("No interfaces found.");
Packit Service 646995
					rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
					goto out;
Packit Service 646995
				}
Packit Service 646995
Packit Service 646995
				for (i = 0; i < iface_count; ++i)
Packit Service 646995
					iface_print_flat(ifaces[i]);
Packit Service 646995
			} else {
Packit Service 646995
				_good(iscsi_iface_get(ctx, iface->name,
Packit Service 646995
						      &iface_info),
Packit Service 646995
				      rc, out);
Packit Service 646995
				iscsi_iface_print_config(iface_info);
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 1:
Packit Service 646995
			/*
Packit Service 646995
			 * TODO: we can display how the ifaces are related to
Packit Service 646995
			 * node records.
Packit Service 646995
			 * And we can add a scsi_host mode which would display
Packit Service 646995
			 * how sessions are related to hosts (scsi_host and
Packit Service 646995
			 * iscsi_sessions are the currently running instance of
Packit Service 646995
			 * an iface or node record).
Packit Service 646995
			 */
Packit Service 646995
			/*
Packit Service 646995
			 * TODO(Gris Ge): Once we have node support from
Packit Service 646995
			 * libopeniscsiusr, change below codes.
Packit Service 646995
			 */
Packit Service 646995
			rc = print_iface_tree(ctx, iface ? iface->name : NULL);
Packit Service 646995
			break;
Packit Service 646995
		default:
Packit Service 646995
			log_error("Invalid info level %d. Try 0 - 1.",
Packit Service 646995
				  info_level);
Packit Service 646995
			rc = LIBISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
out:
Packit Service 646995
	iscsi_ifaces_free(ifaces, iface_count);
Packit Service 646995
	iscsi_iface_free(iface_info);
Packit Service 646995
Packit Service 646995
	if (rec)
Packit Service 646995
		free(rec);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int verify_node_params(struct list_head *params, struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
Packit Service 646995
	if (list_empty(params)) {
Packit Service 646995
		log_error("update requires name and value");
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, params, list) {
Packit Service 646995
		/* compat - old tools used node and iface transport name */
Packit Service 646995
		if (!strncmp(param->name, "iface.", 6) &&
Packit Service 646995
		     strcmp(param->name, "iface.transport_name")) {
Packit Service 646995
			log_error("Cannot modify %s. Use iface mode to update "
Packit Service 646995
				  "this value.", param->name);
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (!strcmp(param->name, "node.transport_name")) {
Packit Service 646995
			free(param->name);
Packit Service 646995
			param->name = strdup("iface.transport_name");
Packit Service 646995
			if (!param->name) {
Packit Service 646995
				log_error("Could not allocate memory for "
Packit Service 646995
					  "param.");
Packit Service 646995
				return ISCSI_ERR_NOMEM;
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
		/*
Packit Service 646995
		 * tmp hack - we added compat crap above for the transport,
Packit Service 646995
		 * but want to fix Doran's issue in this release too. However
Packit Service 646995
		 * his patch is too harsh on many settings and we do not have
Packit Service 646995
		 * time to update apps so we have this tmp hack until we
Packit Service 646995
		 * can settle on a good interface that distros can use
Packit Service 646995
		 * and we can mark stable.
Packit Service 646995
		 */
Packit Service 646995
		if (!strcmp(param->name, "iface.transport_name")) {
Packit Service 646995
			if (iscsi_check_for_running_session(rec)) {
Packit Service 646995
				log_warning("Cannot modify node/iface "
Packit Service 646995
					    "transport name while a session "
Packit Service 646995
					    "is using it. Log out the session "
Packit Service 646995
					    "then update record.");
Packit Service 646995
				return ISCSI_ERR_SESS_EXISTS;
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/* TODO cleanup arguments */
Packit Service 646995
static int exec_node_op(struct iscsi_context *ctx, int op, int do_login,
Packit Service 646995
			int do_logout, int do_show, int do_rescan, int do_stats,
Packit Service 646995
			bool wait, int info_level, struct node_rec *rec,
Packit Service 646995
			struct list_head *params)
Packit Service 646995
{
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	if (rec)
Packit Service 646995
		log_debug(2, "%s: %s:%s node [%s,%s,%d] sid %u", __FUNCTION__,
Packit Service 646995
			  rec->iface.transport_name, rec->iface.name,
Packit Service 646995
			  rec->name, rec->conn[0].address, rec->conn[0].port,
Packit Service 646995
			  rec->session.sid);
Packit Service 646995
Packit Service 646995
	if (op == OP_NEW) {
Packit Service 646995
		rc = add_static_recs(rec);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_rescan) {
Packit Service 646995
		rc = for_each_session(rec, rescan_portal, 1);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_stats) {
Packit Service 646995
		rc = for_each_session(rec, session_stats, 0);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_login && do_logout) {
Packit Service 646995
		log_error("Invalid parameters. Both login and logout passed in");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((do_login || do_logout) && op > OP_NOOP) {
Packit Service 646995
		log_error("Invalid parameters. Login/logout and op passed in");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((!do_login && !do_logout && op == OP_NOOP) &&
Packit Service 646995
	    ((rec == NULL) ||
Packit Service 646995
	     (!strlen(rec->name) && !strlen(rec->conn[0].address) &&
Packit Service 646995
	      !strlen(rec->iface.name)))) {
Packit Service 646995
		rc = print_nodes(ctx, info_level);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_login) {
Packit Service 646995
		rc = login_portals(rec, wait);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_logout) {
Packit Service 646995
		int nr_found;
Packit Service 646995
Packit Service 646995
		rc = iscsi_logout_portals(rec, &nr_found, 1,
Packit Service 646995
					  iscsi_logout_matched_portal);
Packit Service 646995
		if (rc == ISCSI_ERR_NO_OBJS_FOUND)
Packit Service 646995
			log_error("No matching sessions found");
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (op == OP_NOOP || (!do_login && !do_logout && op == OP_SHOW)) {
Packit Service 646995
		rc = print_nodes_config(ctx, do_show ? true : false,
Packit Service 646995
					rec->name, rec->conn[0].address,
Packit Service 646995
					rec->conn[0].port, rec->iface.name);
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (op == OP_UPDATE) {
Packit Service 646995
		rc = verify_node_params(params, rec);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto out;
Packit Service 646995
Packit Service 646995
		rc = for_each_matched_rec(rec, params, idbm_node_set_param);
Packit Service 646995
		goto out;
Packit Service 646995
	} else if (op == OP_DELETE) {
Packit Service 646995
		rc = for_each_matched_rec(rec, NULL, delete_node);
Packit Service 646995
		goto out;
Packit Service 646995
	} else {
Packit Service 646995
		log_error("operation is not supported.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
out:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_fw_disc_op(discovery_rec_t *drec, struct list_head *ifaces,
Packit Service 646995
			   int info_level, int do_login, int op)
Packit Service 646995
{
Packit Service 646995
	LIST_HEAD(targets);
Packit Service 646995
	LIST_HEAD(rec_list);
Packit Service 646995
	LIST_HEAD(new_ifaces);
Packit Service 646995
	struct iface_rec *iface, *tmp_iface;
Packit Service 646995
	struct node_rec *rec, *tmp_rec;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * compat: if the user did not pass any op then we do all
Packit Service 646995
	 * ops for them
Packit Service 646995
	 */
Packit Service 646995
	if (!op)
Packit Service 646995
		op = OP_NEW | OP_DELETE | OP_UPDATE;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * if a user passed in ifaces then we use them and ignore the ibft
Packit Service 646995
	 * net info
Packit Service 646995
	 */
Packit Service 646995
	if (!list_empty(ifaces)) {
Packit Service 646995
		list_for_each_entry_safe(iface, tmp_iface, ifaces, list) {
Packit Service 646995
			rc = iface_conf_read(iface);
Packit Service 646995
			if (rc) {
Packit Service 646995
				log_error("Could not read iface info for %s. "
Packit Service 646995
					  "Make sure an iface config with the "
Packit Service 646995
					  "file name and iface.iscsi_ifacename "
Packit Service 646995
					  "%s is in %s.", iface->name,
Packit Service 646995
					  iface->name, IFACE_CONFIG_DIR);
Packit Service 646995
				list_del_init(&iface->list);
Packit Service 646995
				free(iface);
Packit Service 646995
				continue;
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
		goto discover_fw_tgts;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * Next, check if we see any offload cards. If we do then
Packit Service 646995
	 * we make an iface if needed.
Packit Service 646995
	 *
Packit Service 646995
	 * Note1: if there is not a offload card we do not setup
Packit Service 646995
	 * software iscsi binding with the nic used for booting,
Packit Service 646995
	 * because we do not know if that was intended.
Packit Service 646995
	 *
Packit Service 646995
	 * Note2: we assume that the user probably wanted to access
Packit Service 646995
	 * all targets through all the ifaces instead of being limited
Packit Service 646995
	 * to what you can export in ibft.
Packit Service 646995
	 */
Packit Service 646995
	rc = fw_get_targets(&targets;;
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not get list of targets from firmware. "
Packit Service 646995
			  "(err %d)", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
	rc = iface_create_ifaces_from_boot_contexts(&new_ifaces, &targets;;
Packit Service 646995
	if (rc)
Packit Service 646995
		goto done;
Packit Service 646995
	if (!list_empty(&new_ifaces))
Packit Service 646995
		ifaces = &new_ifaces;
Packit Service 646995
Packit Service 646995
discover_fw_tgts:
Packit Service 646995
	rc = idbm_bind_ifaces_to_nodes(discovery_fw, drec,
Packit Service 646995
				       ifaces, &rec_list);
Packit Service 646995
	if (rc)
Packit Service 646995
		log_error("Could not perform fw discovery.");
Packit Service 646995
	else
Packit Service 646995
		rc = exec_disc_op_on_recs(drec, &rec_list, info_level,
Packit Service 646995
					   do_login, op);
Packit Service 646995
Packit Service 646995
done:
Packit Service 646995
	fw_free_targets(&targets;;
Packit Service 646995
Packit Service 646995
	list_for_each_entry_safe(iface, tmp_iface, &new_ifaces, list) {
Packit Service 646995
		list_del(&iface->list);
Packit Service 646995
		free(iface);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	list_for_each_entry_safe(rec, tmp_rec, &rec_list, list) {
Packit Service 646995
		list_del(&rec->list);
Packit Service 646995
		free(rec);
Packit Service 646995
	}
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_fw_op(discovery_rec_t *drec, struct list_head *ifaces,
Packit Service 646995
		      int info_level, int do_login, int op)
Packit Service 646995
{
Packit Service 646995
	struct boot_context *context;
Packit Service 646995
	LIST_HEAD(targets);
Packit Service 646995
        LIST_HEAD(rec_list);
Packit Service 646995
	struct node_rec *rec;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	if (drec)
Packit Service 646995
		return exec_fw_disc_op(drec, ifaces, info_level, do_login, op);
Packit Service 646995
Packit Service 646995
	/* The following ops do not interact with the DB */
Packit Service 646995
	rc = fw_get_targets(&targets;;
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not get list of targets from firmware. "
Packit Service 646995
			  "(err %d)", rc);
Packit Service 646995
		return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (do_login) {
Packit Service 646995
		list_for_each_entry(context, &targets, list) {
Packit Service 646995
			rec = idbm_create_rec_from_boot_context(context);
Packit Service 646995
			if (!rec) {
Packit Service 646995
				log_error("Could not convert firmware info to "
Packit Service 646995
					  "node record.");
Packit Service 646995
				rc = ISCSI_ERR_NOMEM;
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			iscsi_login_portal(NULL, NULL, rec);
Packit Service 646995
			free(rec);
Packit Service 646995
		}
Packit Service 646995
	} else {
Packit Service 646995
		list_for_each_entry(context, &targets, list)
Packit Service 646995
			fw_print_entry(context);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	fw_free_targets(&targets;;
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void setup_drec_defaults(int type, char *ip, int port,
Packit Service 646995
				struct discovery_rec *drec)
Packit Service 646995
{
Packit Service 646995
	switch (type) {
Packit Service 646995
	case DISCOVERY_TYPE_ISNS:
Packit Service 646995
		idbm_isns_defaults(&drec->u.isns);
Packit Service 646995
		break;
Packit Service 646995
	case DISCOVERY_TYPE_SENDTARGETS:
Packit Service 646995
		idbm_sendtargets_defaults(&drec->u.sendtargets);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("Invalid disc type.");
Packit Service 646995
	}
Packit Service 646995
	strlcpy(drec->address, ip, sizeof(drec->address));
Packit Service 646995
	drec->port = port;
Packit Service 646995
	drec->type = type;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/**
Packit Service 646995
 * exec_discover - prep, add, read and exec discovery on drec
Packit Service 646995
 * @type: discovery type
Packit Service 646995
 * @ip: IP address
Packit Service 646995
 * @port: port
Packit Service 646995
 * @ifaces: list of ifaces to bind to
Packit Service 646995
 * @info_level: print level
Packit Service 646995
 * @do_login: set to 1 if discovery function should also log into portals found
Packit Service 646995
 * @do_discover: set to 1 if discovery was requested
Packit Service 646995
 * @op: ops passed in by user
Packit Service 646995
 * @drec: discovery rec struct
Packit Service 646995
 *
Packit Service 646995
 * This function determines what type of op needs to be executed
Packit Service 646995
 * and will read and add a drec, and perform discovery if needed.
Packit Service 646995
 *
Packit Service 646995
 * returns:
Packit Service 646995
 * 	Greater than 0 - error
Packit Service 646995
 * 	0 - op/discovery completed
Packit Service 646995
 * 	-1 - exec db op
Packit Service 646995
 */
Packit Service 646995
static int exec_discover(int disc_type, char *ip, int port,
Packit Service 646995
			 struct list_head *ifaces, int info_level,
Packit Service 646995
			 int do_login, int do_discover, int op,
Packit Service 646995
			 struct discovery_rec *drec)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	if (ip == NULL) {
Packit Service 646995
		log_error("Please specify portal as <ipaddr>[:<ipport>]");
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (op & OP_NEW && !do_discover) {
Packit Service 646995
		setup_drec_defaults(disc_type, ip, port, drec);
Packit Service 646995
Packit Service 646995
		rc = idbm_add_discovery(drec);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_error("Could not add new discovery record.");
Packit Service 646995
			return rc;
Packit Service 646995
		} else {
Packit Service 646995
			printf("New discovery record for [%s,%d] added.\n", ip,
Packit Service 646995
			       port);
Packit Service 646995
			return 0;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = idbm_discovery_read(drec, disc_type, ip, port);
Packit Service 646995
	if (rc) {
Packit Service 646995
		if (!do_discover) {
Packit Service 646995
			log_error("Discovery record [%s,%d] not found.",
Packit Service 646995
				  ip, port);
Packit Service 646995
			return rc;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		/* Just add default rec for user */
Packit Service 646995
		log_debug(1, "Discovery record [%s,%d] not found!",
Packit Service 646995
			  ip, port);
Packit Service 646995
		setup_drec_defaults(disc_type, ip, port, drec);
Packit Service 646995
		if (!(op & OP_NONPERSISTENT)) {
Packit Service 646995
			rc = idbm_add_discovery(drec);
Packit Service 646995
			if (rc) {
Packit Service 646995
				log_error("Could not add new discovery "
Packit Service 646995
					  "record.");
Packit Service 646995
				return rc;
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
	} else if (!do_discover)
Packit Service 646995
		return -1;
Packit Service 646995
Packit Service 646995
	rc = 0;
Packit Service 646995
	switch (disc_type) {
Packit Service 646995
	case DISCOVERY_TYPE_SENDTARGETS:
Packit Service 646995
	case DISCOVERY_TYPE_ISNS:
Packit Service 646995
		rc = do_target_discovery(drec, ifaces, info_level, do_login, op,
Packit Service 646995
				    0);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("Unsupported discovery type.");
Packit Service 646995
		break;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_disc2_op(int disc_type, char *ip, int port,
Packit Service 646995
			 struct list_head *ifaces, int info_level, int do_login,
Packit Service 646995
			 int do_discover, int op, struct list_head *params,
Packit Service 646995
			 int do_show)
Packit Service 646995
{
Packit Service 646995
	struct discovery_rec drec;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	memset(&drec, 0, sizeof(struct discovery_rec));
Packit Service 646995
	drec.iscsid_req_tmo = -1;
Packit Service 646995
	if (disc_type != -1)
Packit Service 646995
		drec.type = disc_type;
Packit Service 646995
Packit Service 646995
	switch (disc_type) {
Packit Service 646995
	case DISCOVERY_TYPE_SENDTARGETS:
Packit Service 646995
		if (port < 0)
Packit Service 646995
			port = ISCSI_LISTEN_PORT;
Packit Service 646995
Packit Service 646995
		rc = exec_discover(disc_type, ip, port, ifaces, info_level,
Packit Service 646995
				   do_login, do_discover, op, &drec);
Packit Service 646995
		if (rc < 0)
Packit Service 646995
			goto do_db_op;
Packit Service 646995
		goto done;
Packit Service 646995
	case DISCOVERY_TYPE_SLP:
Packit Service 646995
		log_error("SLP discovery is not fully implemented yet.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto done;
Packit Service 646995
	case DISCOVERY_TYPE_ISNS:
Packit Service 646995
		if (port < 0)
Packit Service 646995
			port = ISNS_DEFAULT_PORT;
Packit Service 646995
Packit Service 646995
		rc = exec_discover(disc_type, ip, port, ifaces, info_level,
Packit Service 646995
				   do_login, do_discover, op, &drec);
Packit Service 646995
		if (rc < 0)
Packit Service 646995
			goto do_db_op;
Packit Service 646995
		goto done;
Packit Service 646995
	case DISCOVERY_TYPE_FW:
Packit Service 646995
		if (!do_discover) {
Packit Service 646995
			log_error("Invalid command. Possibly missing "
Packit Service 646995
				  "--discover argument.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto done;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		drec.type = DISCOVERY_TYPE_FW;
Packit Service 646995
		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op);
Packit Service 646995
		goto done;
Packit Service 646995
	default:
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
Packit Service 646995
		if (!ip) {
Packit Service 646995
			 if (op == OP_NOOP || op == OP_SHOW) {
Packit Service 646995
				if (idbm_print_all_discovery(info_level))
Packit Service 646995
					/* successfully found some recs */
Packit Service 646995
					rc = 0;
Packit Service 646995
				else
Packit Service 646995
					rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
			} else
Packit Service 646995
				log_error("Invalid operation. Operation not "
Packit Service 646995
					  "supported.");
Packit Service 646995
		} else if (op)
Packit Service 646995
			log_error("Invalid command. Possibly missing discovery "
Packit Service 646995
				  "--type.");
Packit Service 646995
		else
Packit Service 646995
			log_error("Invalid command. Portal not needed or "
Packit Service 646995
				  "Possibly missing discovery --type.");
Packit Service 646995
		goto done;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
do_db_op:
Packit Service 646995
	rc = 0;
Packit Service 646995
Packit Service 646995
	if (op == OP_NOOP || op == OP_SHOW) {
Packit Service 646995
		if (!idbm_print_discovery_info(&drec, do_show)) {
Packit Service 646995
			log_error("No records found");
Packit Service 646995
			rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
		}
Packit Service 646995
	} else if (op == OP_DELETE) {
Packit Service 646995
		rc = idbm_delete_discovery(&drec);
Packit Service 646995
		if (rc)
Packit Service 646995
			log_error("Unable to delete record!");
Packit Service 646995
	} else if (op == OP_UPDATE) {
Packit Service 646995
		if (list_empty(params)) {
Packit Service 646995
			log_error("Update requires name and value.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto done;
Packit Service 646995
		}
Packit Service 646995
		rc = idbm_discovery_set_param(params, &drec);
Packit Service 646995
	} else {
Packit Service 646995
		log_error("Operation is not supported.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto done;
Packit Service 646995
	}
Packit Service 646995
done:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_disc_op(int disc_type,
Packit Service 646995
			char *ip,
Packit Service 646995
			int port,
Packit Service 646995
			struct list_head *ifaces,
Packit Service 646995
			int info_level,
Packit Service 646995
			int do_login,
Packit Service 646995
			int do_discover,
Packit Service 646995
			int op,
Packit Service 646995
			__attribute__((unused))struct list_head *params,
Packit Service 646995
			int do_show)
Packit Service 646995
{
Packit Service 646995
	struct discovery_rec drec;
Packit Service 646995
	int rc = 0;
Packit Service 646995
Packit Service 646995
	memset(&drec, 0, sizeof(struct discovery_rec));
Packit Service 646995
	drec.iscsid_req_tmo = -1;
Packit Service 646995
Packit Service 646995
	switch (disc_type) {
Packit Service 646995
	case DISCOVERY_TYPE_SENDTARGETS:
Packit Service 646995
		drec.type = DISCOVERY_TYPE_SENDTARGETS;
Packit Service 646995
Packit Service 646995
		if (port < 0)
Packit Service 646995
			port = ISCSI_LISTEN_PORT;
Packit Service 646995
Packit Service 646995
		if (ip == NULL) {
Packit Service 646995
			log_error("Please specify portal as "
Packit Service 646995
				  "<ipaddr>[:<ipport>]");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto done;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		idbm_sendtargets_defaults(&drec.u.sendtargets);
Packit Service 646995
		strlcpy(drec.address, ip, sizeof(drec.address));
Packit Service 646995
		drec.port = port;
Packit Service 646995
		rc = do_target_discovery(&drec, ifaces, info_level,
Packit Service 646995
				    do_login, op, 1);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto done;
Packit Service 646995
		break;
Packit Service 646995
	case DISCOVERY_TYPE_SLP:
Packit Service 646995
		log_error("SLP discovery is not fully implemented yet.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		break;
Packit Service 646995
	case DISCOVERY_TYPE_ISNS:
Packit Service 646995
		if (!ip) {
Packit Service 646995
			log_error("Please specify portal as "
Packit Service 646995
				  "<ipaddr>:[<ipport>]");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto done;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		strlcpy(drec.address, ip, sizeof(drec.address));
Packit Service 646995
		if (port < 0)
Packit Service 646995
			drec.port = ISNS_DEFAULT_PORT;
Packit Service 646995
		else
Packit Service 646995
			drec.port = port;
Packit Service 646995
Packit Service 646995
		drec.type = DISCOVERY_TYPE_ISNS;
Packit Service 646995
		rc = do_target_discovery(&drec, ifaces, info_level,
Packit Service 646995
					do_login, op, 0);
Packit Service 646995
		if (rc)
Packit Service 646995
			goto done;
Packit Service 646995
		break;
Packit Service 646995
	case DISCOVERY_TYPE_FW:
Packit Service 646995
		drec.type = DISCOVERY_TYPE_FW;
Packit Service 646995
		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		if (ip) {
Packit Service 646995
			/*
Packit Service 646995
			 * We only have sendtargets disc recs in discovery
Packit Service 646995
			 * mode, so we can hardcode the port check to the
Packit Service 646995
			 * iscsi default here.
Packit Service 646995
			 *
Packit Service 646995
			 * For isns or slp recs then discovery db mode
Packit Service 646995
			 * must be used.
Packit Service 646995
			 */
Packit Service 646995
			if (port < 0)
Packit Service 646995
				port = ISCSI_LISTEN_PORT;
Packit Service 646995
Packit Service 646995
			if (idbm_discovery_read(&drec,
Packit Service 646995
						DISCOVERY_TYPE_SENDTARGETS,
Packit Service 646995
						ip, port)) {
Packit Service 646995
				log_error("Discovery record [%s,%d] "
Packit Service 646995
					  "not found!", ip, port);
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto done;
Packit Service 646995
			}
Packit Service 646995
			if ((do_discover || do_login) &&
Packit Service 646995
			    drec.type == DISCOVERY_TYPE_SENDTARGETS) {
Packit Service 646995
				rc = do_target_discovery(&drec, ifaces,
Packit Service 646995
						info_level, do_login,
Packit Service 646995
						op, 0);
Packit Service 646995
			} else if (op == OP_NOOP || op == OP_SHOW) {
Packit Service 646995
				if (!idbm_print_discovery_info(&drec,
Packit Service 646995
							       do_show)) {
Packit Service 646995
					log_error("No records found");
Packit Service 646995
					rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
				}
Packit Service 646995
			} else if (op == OP_DELETE) {
Packit Service 646995
				rc = idbm_delete_discovery(&drec);
Packit Service 646995
				if (rc)
Packit Service 646995
					log_error("Unable to delete record!");
Packit Service 646995
			} else if (op == OP_UPDATE || op == OP_NEW) {
Packit Service 646995
				log_error("Operations new and update for "
Packit Service 646995
					  "discovery mode is not supported. "
Packit Service 646995
					  "Use discoverydb mode.");
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto done;
Packit Service 646995
			} else {
Packit Service 646995
				log_error("Invalid operation.");
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto done;
Packit Service 646995
			}
Packit Service 646995
		} else if (op == OP_NOOP || op == OP_SHOW) {
Packit Service 646995
			if (!idbm_print_all_discovery(info_level))
Packit Service 646995
				rc = ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
			goto done;
Packit Service 646995
		} else {
Packit Service 646995
			log_error("Invalid operation.");
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto done;
Packit Service 646995
		}
Packit Service 646995
		/* fall through */
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
done:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static uint64_t parse_host_info(char *optarg, int *rc)
Packit Service 646995
{
Packit Service 646995
	int err = 0;
Packit Service 646995
	uint64_t host_no;
Packit Service 646995
Packit Service 646995
	*rc = 0;
Packit Service 646995
	if (strstr(optarg, ":")) {
Packit Service 646995
		transport_probe_for_offload();
Packit Service 646995
Packit Service 646995
		host_no = iscsi_sysfs_get_host_no_from_hwaddress(optarg,
Packit Service 646995
								 &err;;
Packit Service 646995
		if (err) {
Packit Service 646995
			log_error("Could not match MAC to host.");
Packit Service 646995
			*rc = ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
	} else {
Packit Service 646995
		errno = 0;	// ensure errors from strtoull are real
Packit Service 646995
		host_no = strtoull(optarg, NULL, 10);
Packit Service 646995
		if (errno || (host_no > MAX_HOST_NO)) {
Packit Service 646995
			if (host_no > MAX_HOST_NO)
Packit Service 646995
				errno = ERANGE;
Packit Service 646995
Packit Service 646995
			log_error("Invalid host no %s. %s.",
Packit Service 646995
				  optarg, strerror(errno));
Packit Service 646995
			*rc = ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
	return host_no;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static char *iscsi_ping_stat_strs[] = {
Packit Service 646995
	/* ISCSI_PING_SUCCESS */
Packit Service 646995
	"success",
Packit Service 646995
	/* ISCSI_PING_FW_DISABLED */
Packit Service 646995
	"firmware disabled",
Packit Service 646995
	/* ISCSI_PING_IPADDR_INVALID */
Packit Service 646995
	"invalid IP address",
Packit Service 646995
	/* ISCSI_PING_LINKLOCAL_IPV6_ADDR_INVALID */
Packit Service 646995
	"invalid link local IPv6 address",
Packit Service 646995
	/* ISCSI_PING_TIMEOUT */
Packit Service 646995
	"timed out",
Packit Service 646995
	/* ISCSI_PING_INVALID_DEST_ADDR */
Packit Service 646995
	"invalid destination address",
Packit Service 646995
	/* ISCSI_PING_OVERSIZE_PACKET */
Packit Service 646995
	"oversized packet",
Packit Service 646995
	/* ISCSI_PING_ICMP_ERROR */
Packit Service 646995
	"ICMP error",
Packit Service 646995
	/* ISCSI_PING_MAX_REQ_EXCEEDED */
Packit Service 646995
	"Max request exceeded",
Packit Service 646995
	/* ISCSI_PING_NO_ARP_RECEIVED */
Packit Service 646995
	"No ARP response received",
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static char *iscsi_ping_stat_to_str(uint32_t status)
Packit Service 646995
{
Packit Service 646995
	if (status == 0 || status > ISCSI_PING_NO_ARP_RECEIVED) {
Packit Service 646995
		log_error("Invalid ping status %u", status);
Packit Service 646995
		return NULL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return iscsi_ping_stat_strs[status];
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int exec_ping_op(struct iface_rec *iface, char *ip, int size, int count,
Packit Service 646995
			int interval)
Packit Service 646995
{
Packit Service 646995
	int rc = ISCSI_ERR;
Packit Service 646995
	uint32_t iface_type = ISCSI_IFACE_TYPE_IPV4;
Packit Service 646995
	struct iscsi_transport *t = NULL;
Packit Service 646995
	uint32_t host_no, status = 0;
Packit Service 646995
	struct sockaddr_storage addr;
Packit Service 646995
	struct host_info hinfo;
Packit Service 646995
	int i;
Packit Service 646995
Packit Service 646995
	if (!iface) {
Packit Service 646995
		log_error("Ping requires iface.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!ip) {
Packit Service 646995
		log_error("Ping requires destination ipaddress.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (size <= 0) {
Packit Service 646995
		log_error("Invalid packet size: %d.", size);
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (count <= 0) {
Packit Service 646995
		log_error("Invalid number of packets to transmit: %d.", count);
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (interval < 0) {
Packit Service 646995
		log_error("Invalid timing interval: %d.", interval);
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = iface_conf_read(iface);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not read iface %s (%d).", iface->name, rc);
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
Packit Service 646995
	iface_type = iface_get_iptype(iface);
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_name(iface->transport_name);
Packit Service 646995
	if (!t) {
Packit Service 646995
		log_error("Can't find transport.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
Packit Service 646995
	if (host_no == 0) {
Packit Service 646995
		log_error("Can't find host_no.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = resolve_address(ip, NULL, &addr);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Invalid IP address.");
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto ping_exit;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* TODO: move this. It is needed by interface for pid */
Packit Service 646995
	srand(time(NULL));
Packit Service 646995
Packit Service 646995
	for (i = 1; i <= count; i++) {
Packit Service 646995
		/*
Packit Service 646995
		 * To support drivers like bnx2i that do not use
Packit Service 646995
		 * the iscsi iface to send a ping, we invoke transport
Packit Service 646995
		 * callout here.
Packit Service 646995
		 */
Packit Service 646995
		status = 0;
Packit Service 646995
		if (t->template->exec_ping) {
Packit Service 646995
			if (!strlen(iface->netdev)) {
Packit Service 646995
				memset(&hinfo, 0, sizeof(hinfo));
Packit Service 646995
				hinfo.host_no = host_no;
Packit Service 646995
				iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
Packit Service 646995
				strcpy(iface->netdev, hinfo.iface.netdev);
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			rc = iscsi_set_net_config(t, NULL, iface);
Packit Service 646995
			if (rc && (rc != ISCSI_ERR_AGAIN))
Packit Service 646995
				goto ping_err;
Packit Service 646995
Packit Service 646995
			rc = t->template->exec_ping(t, iface, size, &addr,
Packit Service 646995
						    &status);
Packit Service 646995
		} else {
Packit Service 646995
			rc = ipc->exec_ping(t->handle, host_no,
Packit Service 646995
					    (struct sockaddr *)&addr,
Packit Service 646995
					    iface->iface_num, iface_type,
Packit Service 646995
					    (uint32_t)size, &status);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
ping_err:
Packit Service 646995
		if (!rc && !status)
Packit Service 646995
			printf("Ping %d completed\n", i);
Packit Service 646995
		else if (status)
Packit Service 646995
			printf("Ping %d failed: %s\n", i,
Packit Service 646995
				iscsi_ping_stat_to_str(status));
Packit Service 646995
		else
Packit Service 646995
			printf("Ping %d failed: %s\n", i, iscsi_err_to_str(rc));
Packit Service 646995
Packit Service 646995
		if (i < count)
Packit Service 646995
			sleep(interval);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
ping_exit:
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int
Packit Service 646995
main(int argc, char **argv)
Packit Service 646995
{
Packit Service 646995
	char *ip = NULL, *name = NULL, *value = NULL;
Packit Service 646995
	char *targetname = NULL, *group_session_mgmt_mode = NULL;
Packit Service 646995
	int ch, longindex, mode=-1, port=-1, do_login=0, do_rescan=0;
Packit Service 646995
	int rc=0, sid=-1, op=OP_NOOP, type=-1, do_logout=0, do_stats=0;
Packit Service 646995
	int do_login_all=0, do_logout_all=0, info_level=-1, num_ifaces = 0;
Packit Service 646995
	int tpgt = PORTAL_GROUP_TAG_UNKNOWN, killiscsid=-1, do_show=0;
Packit Service 646995
	int packet_size=32, ping_count=1, ping_interval=0;
Packit Service 646995
	int do_discover = 0, sub_mode = -1;
Packit Service 646995
	int portal_type = -1;
Packit Service 646995
	int timeout = ISCSID_REQ_TIMEOUT;
Packit Service 646995
	struct sigaction sa_old;
Packit Service 646995
	struct sigaction sa_new;
Packit Service 646995
	LIST_HEAD(ifaces);
Packit Service 646995
	struct iface_rec *iface = NULL, *tmp;
Packit Service 646995
	struct node_rec *rec = NULL;
Packit Service 646995
	uint32_t host_no =  MAX_HOST_NO + 1;
Packit Service 646995
	uint64_t index = ULLONG_MAX;
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	LIST_HEAD(params);
Packit Service 646995
	struct iscsi_context *ctx = NULL;
Packit Service 646995
	int librc = LIBISCSI_OK;
Packit Service 646995
	struct iscsi_session **ses = NULL;
Packit Service 646995
	uint32_t se_count = 0;
Packit Service 646995
	struct iscsi_session *se = NULL;
Packit Service 646995
	bool wait = true;
Packit Service 646995
Packit Service 646995
	ctx = iscsi_context_new();
Packit Service 646995
	if (ctx == NULL) {
Packit Service 646995
		log_error("No memory");
Packit Service 646995
		goto out;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* do not allow ctrl-c for now... */
Packit Service 646995
	memset(&sa_old, 0, sizeof(struct sigaction));
Packit Service 646995
	memset(&sa_new, 0, sizeof(struct sigaction));
Packit Service 646995
Packit Service 646995
	sa_new.sa_handler = catch_sigint;
Packit Service 646995
	sigemptyset(&sa_new.sa_mask);
Packit Service 646995
	sa_new.sa_flags = 0;
Packit Service 646995
	sigaction(SIGINT, &sa_new, &sa_old );
Packit Service 646995
Packit Service 646995
	umask(0177);
Packit Service 646995
Packit Service 646995
	/* enable stdout logging */
Packit Service 646995
	log_init(program_name, 1024, log_do_log_std, NULL);
Packit Service 646995
	sysfs_init();
Packit Service 646995
Packit Service 646995
	optopt = 0;
Packit Service 646995
	while ((ch = getopt_long(argc, argv, short_options,
Packit Service 646995
				 long_options, &longindex)) >= 0) {
Packit Service 646995
		switch (ch) {
Packit Service 646995
		case 'k':
Packit Service 646995
			killiscsid = atoi(optarg);
Packit Service 646995
			if (killiscsid < 0) {
Packit Service 646995
				log_error("Invalid killiscsid priority %d "
Packit Service 646995
					  "Priority must be greater than or "
Packit Service 646995
					  "equal to zero.", killiscsid);
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 't':
Packit Service 646995
			type = str_to_type(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'o':
Packit Service 646995
			op |= str_to_op(optarg);
Packit Service 646995
			if (op == OP_NOOP) {
Packit Service 646995
				log_error("can not recognize operation: '%s'",
Packit Service 646995
					optarg);
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 'n':
Packit Service 646995
			name = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'v':
Packit Service 646995
			value = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'H':
Packit Service 646995
			host_no = parse_host_info(optarg, &rc);
Packit Service 646995
			if (rc)
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			break;
Packit Service 646995
		case 'r':
Packit Service 646995
			sid = iscsi_sysfs_get_sid_from_path(optarg);
Packit Service 646995
			if (sid < 0) {
Packit Service 646995
				log_error("invalid sid '%s'",
Packit Service 646995
					  optarg);
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 'R':
Packit Service 646995
			do_rescan = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'P':
Packit Service 646995
			info_level = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'D':
Packit Service 646995
			do_discover = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'l':
Packit Service 646995
			do_login = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'u':
Packit Service 646995
			do_logout = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'U':
Packit Service 646995
			do_logout_all = 1;
Packit Service 646995
			group_session_mgmt_mode= optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'L':
Packit Service 646995
			do_login_all= 1;
Packit Service 646995
			group_session_mgmt_mode= optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 's':
Packit Service 646995
			do_stats = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'S':
Packit Service 646995
			do_show = 1;
Packit Service 646995
			break;
Packit Service 646995
		case 'd':
Packit Service 646995
			log_level = atoi(optarg);
Packit Service 646995
			if (log_level >= 8)
Packit Service 646995
				iscsi_context_log_priority_set
Packit Service 646995
					(ctx, LIBISCSI_LOG_PRIORITY_DEBUG);
Packit Service 646995
			else if (log_level >= 4)
Packit Service 646995
				iscsi_context_log_priority_set
Packit Service 646995
					(ctx, LIBISCSI_LOG_PRIORITY_INFO);
Packit Service 646995
			else if (log_level >= 2)
Packit Service 646995
				iscsi_context_log_priority_set
Packit Service 646995
					(ctx, LIBISCSI_LOG_PRIORITY_WARNING);
Packit Service 646995
			else
Packit Service 646995
				iscsi_context_log_priority_set
Packit Service 646995
					(ctx, LIBISCSI_LOG_PRIORITY_ERROR);
Packit Service 646995
			break;
Packit Service 646995
		case 'm':
Packit Service 646995
			mode = str_to_mode(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'C':
Packit Service 646995
			sub_mode = str_to_submode(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'T':
Packit Service 646995
			targetname = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'p':
Packit Service 646995
			ip = str_to_ipport(optarg, &port, &tpgt);
Packit Service 646995
			break;
Packit Service 646995
		case 'a':
Packit Service 646995
			ip = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'b':
Packit Service 646995
			packet_size = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'c':
Packit Service 646995
			ping_count = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'i':
Packit Service 646995
			ping_interval = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'I':
Packit Service 646995
			iface = iface_alloc(optarg, &rc);
Packit Service 646995
			if (rc == ISCSI_ERR_INVAL) {
Packit Service 646995
				printf("Invalid iface name %s. Must be from "
Packit Service 646995
					"1 to %d characters.\n",
Packit Service 646995
					optarg, ISCSI_MAX_IFACE_LEN - 1);
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			} else if (!iface || rc) {
Packit Service 646995
				printf("Could not add iface %s.", optarg);
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			list_add_tail(&iface->list, &ifaces);
Packit Service 646995
			num_ifaces++;
Packit Service 646995
			break;
Packit Service 646995
		case 'V':
Packit Service 646995
			printf("%s version %s\n", program_name,
Packit Service 646995
				ISCSI_VERSION_STR);
Packit Service 646995
			return 0;
Packit Service 646995
		case 'x':
Packit Service 646995
			errno = 0;	// ensure errors from strtoull are real
Packit Service 646995
			index = strtoull(optarg, NULL, 10);
Packit Service 646995
			if (errno) {
Packit Service 646995
				log_error("Invalid index %s. %s.",
Packit Service 646995
					  optarg, strerror(errno));
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 'A':
Packit Service 646995
			portal_type = str_to_portal_type(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'W':
Packit Service 646995
			wait = false;
Packit Service 646995
			break;
Packit Service 646995
		case 'h':
Packit Service 646995
			usage(0);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (name && value) {
Packit Service 646995
			param = idbm_alloc_user_param(name, value);
Packit Service 646995
			if (!param) {
Packit Service 646995
				log_error("Cannot allocate memory for params.");
Packit Service 646995
				rc = ISCSI_ERR_NOMEM;
Packit Service 646995
				goto free_ifaces;
Packit Service 646995
			}
Packit Service 646995
			list_add_tail(&param->list, &params);
Packit Service 646995
			name = NULL;
Packit Service 646995
			value = NULL;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (optopt) {
Packit Service 646995
		log_error("unrecognized character '%c'", optopt);
Packit Service 646995
		rc = ISCSI_ERR_INVAL;
Packit Service 646995
		goto free_ifaces;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (killiscsid >= 0) {
Packit Service 646995
		kill_iscsid(killiscsid, timeout);
Packit Service 646995
		goto free_ifaces;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (mode < 0)
Packit Service 646995
		usage(ISCSI_ERR_INVAL);
Packit Service 646995
Packit Service 646995
	if (mode == MODE_FW) {
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "dml", 0))) {
Packit Service 646995
			log_error("fw mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto free_ifaces;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc = exec_fw_op(NULL, NULL, info_level, do_login, op);
Packit Service 646995
		goto free_ifaces;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	increase_max_files();
Packit Service 646995
	if (idbm_init(get_config_file)) {
Packit Service 646995
		log_warning("exiting due to idbm configuration error");
Packit Service 646995
		rc = ISCSI_ERR_IDBM;
Packit Service 646995
		goto free_ifaces;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	switch (mode) {
Packit Service 646995
	case MODE_HOST:
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "CHdmPotnvxA", 0))) {
Packit Service 646995
			log_error("host mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
		if (sub_mode != -1) {
Packit Service 646995
			switch (sub_mode) {
Packit Service 646995
			case MODE_CHAP:
Packit Service 646995
				if (!op || (host_no > MAX_HOST_NO)) {
Packit Service 646995
					log_error("CHAP mode requires host "
Packit Service 646995
						"no and valid operation");
Packit Service 646995
					rc = ISCSI_ERR_INVAL;
Packit Service 646995
					break;
Packit Service 646995
				}
Packit Service 646995
Packit Service 646995
				if (index == ULLONG_MAX)
Packit Service 646995
					index = (uint64_t)MAX_CHAP_ENTRIES + 1;
Packit Service 646995
Packit Service 646995
				rc = exec_host_chap_op(op, info_level, host_no,
Packit Service 646995
						       index, &params);
Packit Service 646995
				break;
Packit Service 646995
			case MODE_FLASHNODE:
Packit Service 646995
				if (host_no > MAX_HOST_NO) {
Packit Service 646995
					log_error("FLASHNODE mode requires host no");
Packit Service 646995
					rc = ISCSI_ERR_INVAL;
Packit Service 646995
					break;
Packit Service 646995
				}
Packit Service 646995
Packit Service 646995
				if (index == ULLONG_MAX)
Packit Service 646995
					index = (uint64_t)MAX_FLASHNODE_IDX + 1;
Packit Service 646995
Packit Service 646995
				rc = exec_flashnode_op(op, info_level, host_no,
Packit Service 646995
						       index, portal_type,
Packit Service 646995
						       &params);
Packit Service 646995
				break;
Packit Service 646995
			case MODE_HOST_STATS:
Packit Service 646995
				if (host_no > MAX_HOST_NO) {
Packit Service 646995
					log_error("STATS mode requires host no");
Packit Service 646995
					rc = ISCSI_ERR_INVAL;
Packit Service 646995
					break;
Packit Service 646995
				}
Packit Service 646995
Packit Service 646995
				rc = exec_host_stats_op(op, info_level,
Packit Service 646995
							host_no);
Packit Service 646995
				break;
Packit Service 646995
Packit Service 646995
			default:
Packit Service 646995
				log_error("Invalid Sub Mode");
Packit Service 646995
				break;
Packit Service 646995
			}
Packit Service 646995
		} else {
Packit Service 646995
			librc = iscsi_sessions_get(ctx, &ses, &se_count);
Packit Service 646995
Packit Service 646995
			if (librc != LIBISCSI_OK) {
Packit Service 646995
				log_error("Failed to query iSCSI sessions, "
Packit Service 646995
					  "error %d: %s", librc,
Packit Service 646995
					  iscsi_strerror(librc));
Packit Service 646995
				/* libopeniscsiusr rc is one-to-one map to iscsiadm
Packit Service 646995
				 * rc
Packit Service 646995
				 */
Packit Service 646995
				rc = librc;
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
			rc = host_info_print(info_level, host_no, ses,
Packit Service 646995
					     se_count);
Packit Service 646995
		}
Packit Service 646995
		break;
Packit Service 646995
	case MODE_IFACE:
Packit Service 646995
		iscsi_default_iface_setup(ctx);
Packit Service 646995
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "HIdnvmPoCabci", 0))) {
Packit Service 646995
			log_error("iface mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (!list_empty(&ifaces)) {
Packit Service 646995
			iface = list_entry(ifaces.next, struct iface_rec,
Packit Service 646995
					   list);
Packit Service 646995
			if (num_ifaces > 1)
Packit Service 646995
				log_error("iface mode only accepts one "
Packit Service 646995
					  "interface. Using the first one "
Packit Service 646995
					  "%s.", iface->name);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (sub_mode == MODE_PING)
Packit Service 646995
			rc = exec_ping_op(iface, ip, packet_size, ping_count,
Packit Service 646995
					  ping_interval);
Packit Service 646995
		else
Packit Service 646995
			rc = exec_iface_op(ctx, op, do_show, info_level, iface,
Packit Service 646995
					   host_no, &params);
Packit Service 646995
Packit Service 646995
		break;
Packit Service 646995
	case MODE_DISCOVERYDB:
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "DSIPdmntplov", 0))) {
Packit Service 646995
			log_error("discovery mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc = exec_disc2_op(type, ip, port, &ifaces, info_level,
Packit Service 646995
				   do_login, do_discover, op, &params,
Packit Service 646995
				   do_show);
Packit Service 646995
		break;
Packit Service 646995
	case MODE_DISCOVERY:
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "DSIPdmntplov", 0))) {
Packit Service 646995
			log_error("discovery mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc = exec_disc_op(type, ip, port, &ifaces, info_level,
Packit Service 646995
				  do_login, do_discover, op, &params,
Packit Service 646995
				  do_show);
Packit Service 646995
		break;
Packit Service 646995
	case MODE_NODE:
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv, "RsPIdmlSonvupTULW",
Packit Service 646995
					     0))) {
Packit Service 646995
			log_error("node mode: option '-%c' is not "
Packit Service 646995
				  "allowed/supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (do_login_all) {
Packit Service 646995
			rc = login_by_startup(group_session_mgmt_mode, wait);
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (do_logout_all) {
Packit Service 646995
			rc = logout_by_startup(group_session_mgmt_mode);
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (!list_empty(&ifaces)) {
Packit Service 646995
			iface = list_entry(ifaces.next, struct iface_rec,
Packit Service 646995
					   list);
Packit Service 646995
			if (num_ifaces > 1)
Packit Service 646995
				log_error("NODE mode only accepts one "
Packit Service 646995
					  "interface. Using the first one "
Packit Service 646995
					  "driver %s hwaddress %s ipaddress "
Packit Service 646995
					  "%s.", iface->transport_name,
Packit Service 646995
					  iface->hwaddress, iface->ipaddress);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (ip && port == -1)
Packit Service 646995
			port = ISCSI_LISTEN_PORT;
Packit Service 646995
Packit Service 646995
		rec = idbm_create_rec(targetname, tpgt, ip, port, iface, 1);
Packit Service 646995
		if (!rec) {
Packit Service 646995
			rc = ISCSI_ERR_NOMEM;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc = exec_node_op(ctx, op, do_login, do_logout, do_show,
Packit Service 646995
				  do_rescan, do_stats, wait, info_level, rec,
Packit Service 646995
				  &params);
Packit Service 646995
		break;
Packit Service 646995
	case MODE_SESSION:
Packit Service 646995
		if ((rc = verify_mode_params(argc, argv,
Packit Service 646995
					      "PiRdrmusonuSv", 1))) {
Packit Service 646995
			log_error("session mode: option '-%c' is not "
Packit Service 646995
				  "allowed or supported", rc);
Packit Service 646995
			rc = ISCSI_ERR_INVAL;
Packit Service 646995
			goto out;
Packit Service 646995
		}
Packit Service 646995
		if (sid >= 0) {
Packit Service 646995
			char session[64];
Packit Service 646995
			struct session_info *info;
Packit Service 646995
Packit Service 646995
			snprintf(session, 63, "session%d", sid);
Packit Service 646995
			session[63] = '\0';
Packit Service 646995
Packit Service 646995
			info = calloc(1, sizeof(*info));
Packit Service 646995
			if (!info) {
Packit Service 646995
				rc = ISCSI_ERR_NOMEM;
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
			info->iscsid_req_tmo = -1;
Packit Service 646995
Packit Service 646995
			rc = iscsi_sysfs_get_sessioninfo_by_id(info, session);
Packit Service 646995
			if (rc) {
Packit Service 646995
				log_error("Could not get session info for sid "
Packit Service 646995
					  "%d", sid);
Packit Service 646995
				goto free_info;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			/*
Packit Service 646995
			 * We should be able to go on, but for now
Packit Service 646995
			 * we only support session mode ops if the module
Packit Service 646995
			 * is loaded and we support that module.
Packit Service 646995
			 */
Packit Service 646995
			if (!iscsi_sysfs_get_transport_by_sid(sid))
Packit Service 646995
				goto free_info;
Packit Service 646995
Packit Service 646995
			if (!do_logout && !do_rescan && !do_stats &&
Packit Service 646995
			    op == OP_NOOP && info_level > 0) {
Packit Service 646995
				librc = iscsi_session_get
Packit Service 646995
					(ctx, sid & UINT32_MAX, &se);
Packit Service 646995
				if (librc != LIBISCSI_OK) {
Packit Service 646995
					log_error("Failed to query iSCSI "
Packit Service 646995
						  "session %d, error %d: %s",
Packit Service 646995
						  sid, librc,
Packit Service 646995
						  iscsi_strerror(librc));
Packit Service 646995
					rc = ISCSI_ERR_INVAL;
Packit Service 646995
					goto out;
Packit Service 646995
				}
Packit Service 646995
				ses = (struct iscsi_session **)
Packit Service 646995
					calloc(1,
Packit Service 646995
					       sizeof(struct iscsi_session *));
Packit Service 646995
				ses[0] = se;
Packit Service 646995
				se_count = 1;
Packit Service 646995
				rc = session_info_print(info_level, ses,
Packit Service 646995
							se_count, do_show);
Packit Service 646995
				goto free_info;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			rec = idbm_create_rec(info->targetname,
Packit Service 646995
					      info->tpgt,
Packit Service 646995
					      info->persistent_address,
Packit Service 646995
					      info->persistent_port,
Packit Service 646995
					      &info->iface, 1);
Packit Service 646995
			if (!rec) {
Packit Service 646995
				rc = ISCSI_ERR_NOMEM;
Packit Service 646995
				goto free_info;
Packit Service 646995
			}
Packit Service 646995
			rec->session.info = info;
Packit Service 646995
			rec->session.sid = sid;
Packit Service 646995
Packit Service 646995
			/*
Packit Service 646995
			 * A "new" session means to login a multiple of the
Packit Service 646995
			 * currently-detected session.
Packit Service 646995
			 */
Packit Service 646995
			if (op == OP_NEW) {
Packit Service 646995
				op = OP_NOOP;
Packit Service 646995
				do_login = 1;
Packit Service 646995
				rec->session.multiple = 1;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			/* drop down to node ops */
Packit Service 646995
			rc = exec_node_op(ctx, op, do_login, do_logout, do_show,
Packit Service 646995
					  do_rescan, do_stats, wait, info_level,
Packit Service 646995
					  rec, &params);
Packit Service 646995
free_info:
Packit Service 646995
			free(info);
Packit Service 646995
			goto out;
Packit Service 646995
		} else {
Packit Service 646995
			if (op == OP_NEW) {
Packit Service 646995
				log_error("session mode: Operation 'new' only "
Packit Service 646995
					  "allowed with specific session IDs");
Packit Service 646995
				rc = ISCSI_ERR_INVAL;
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
			if (do_logout || do_rescan || do_stats) {
Packit Service 646995
				rc = exec_node_op(ctx, op, do_login, do_logout,
Packit Service 646995
						 do_show, do_rescan, do_stats,
Packit Service 646995
						 wait, info_level, NULL, &params);
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			librc = iscsi_sessions_get(ctx, &ses, &se_count);
Packit Service 646995
Packit Service 646995
			if (librc != LIBISCSI_OK) {
Packit Service 646995
				log_error("Failed to query iSCSI sessions, "
Packit Service 646995
					  "error %d: %s", librc,
Packit Service 646995
					  iscsi_strerror(librc));
Packit Service 646995
				/* libopeniscsiusr rc is one-to-one map to iscsiadm
Packit Service 646995
				 * rc
Packit Service 646995
				 */
Packit Service 646995
				rc = librc;
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
			if (se_count == 0) {
Packit Service 646995
				log_error("No active sessions.");
Packit Service 646995
				rc =ISCSI_ERR_NO_OBJS_FOUND;
Packit Service 646995
				goto out;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			rc = session_info_print(info_level, ses, se_count,
Packit Service 646995
						do_show);
Packit Service 646995
Packit Service 646995
		}
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		log_error("This mode is not yet supported");
Packit Service 646995
		/* fall through */
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
out:
Packit Service 646995
	iscsi_context_free(ctx);
Packit Service 646995
	if (rec)
Packit Service 646995
		free(rec);
Packit Service 646995
	iscsi_sessions_free(ses, se_count);
Packit Service 646995
	idbm_terminate();
Packit Service 646995
free_ifaces:
Packit Service 646995
	list_for_each_entry_safe(iface, tmp, &ifaces, list) {
Packit Service 646995
		list_del(&iface->list);
Packit Service 646995
		free(iface);
Packit Service 646995
	}
Packit Service 646995
	free_transports();
Packit Service 646995
	sysfs_cleanup();
Packit Service 646995
	return rc;
Packit Service 646995
}