Blame libiscsi/libiscsi.c

Packit Service 2a7015
/*
Packit Service 2a7015
 * iSCSI Administration library
Packit Service 2a7015
 *
Packit Service 2a7015
 * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
Packit Service 2a7015
 * Copyright (C) 2008-2009 Hans de Goede <hdegoede@redhat.com>
Packit Service 6efcfa
 * Copyright (C) 2015      Peter Hatina <phatina@redhat.com>
Packit Service 2a7015
 * maintained by open-iscsi@googlegroups.com
Packit Service 2a7015
 *
Packit Service 2a7015
 * This program is free software; you can redistribute it and/or modify
Packit Service 2a7015
 * it under the terms of the GNU General Public License as published
Packit Service 2a7015
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 2a7015
 * (at your option) any later version.
Packit Service 2a7015
 *
Packit Service 2a7015
 * This program is distributed in the hope that it will be useful, but
Packit Service 2a7015
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2a7015
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 2a7015
 * General Public License for more details.
Packit Service 2a7015
 *
Packit Service 2a7015
 * See the file COPYING included with this distribution for more details.
Packit Service 2a7015
 */
Packit Service 2a7015
Packit Service 2a7015
#include <stdio.h>
Packit Service 2a7015
#include <stdlib.h>
Packit Service 2a7015
#include <string.h>
Packit Service 2a7015
#include <errno.h>
Packit Service 2a7015
#include <unistd.h>
Packit Service 2a7015
#include <sys/syslog.h>
Packit Service 2a7015
#include "libiscsi.h"
Packit Service 2a7015
#include "idbm.h"
Packit Service 2a7015
#include "discovery.h"
Packit Service 2a7015
#include "log.h"
Packit Service 2a7015
#include "sysfs.h"
Packit Service 2a7015
#include "iscsi_sysfs.h"
Packit Service 2a7015
#include "session_info.h"
Packit Service 2a7015
#include "iscsi_util.h"
Packit Service 2a7015
#include "sysdeps.h"
Packit Service 2a7015
#include "iface.h"
Packit Service 2a7015
#include "iscsi_proto.h"
Packit Service 2a7015
#include "fw_context.h"
Packit Service 2a7015
#include "iscsid_req.h"
Packit Service 2a7015
#include "iscsi_err.h"
Packit Service 2a7015
Packit Service 2a7015
#define CHECK(a) { context->error_str[0] = 0; rc = a; if (rc) goto leave; }
Packit Service 2a7015
Packit Service 2a7015
/* UGLY, not thread safe :( */
Packit Service 2a7015
static int sysfs_initialized = 0;
Packit Service 2a7015
Packit Service 2a7015
struct libiscsi_context {
Packit Service 2a7015
	char error_str[256];
Packit Service 2a7015
	/* For get_parameter_helper() */
Packit Service 2a7015
	const char *parameter;
Packit Service 2a7015
	char *value;
Packit Service 2a7015
};
Packit Service 2a7015
Packit Service 2a7015
static void libiscsi_log(int prio, void *priv, const char *fmt, va_list ap)
Packit Service 2a7015
{
Packit Service 2a7015
	struct libiscsi_context *context = priv;
Packit Service 2a7015
Packit Service 2a7015
	if (prio > LOG_ERR) /* We are only interested in errors (or worse) */
Packit Service 2a7015
		return;
Packit Service 2a7015
Packit Service 2a7015
	vsnprintf(context->error_str, sizeof(context->error_str), fmt, ap);
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
struct libiscsi_context *libiscsi_init(void)
Packit Service 2a7015
{
Packit Service 2a7015
	struct libiscsi_context *context;
Packit Service 2a7015
Packit Service 2a7015
	context = calloc(1, sizeof *context);
Packit Service 2a7015
	if (!context)
Packit Service 2a7015
		return NULL;
Packit Service 2a7015
Packit Service 2a7015
	log_init("libiscsi", 1024, libiscsi_log, context);
Packit Service 2a7015
	if (!sysfs_initialized) {
Packit Service 2a7015
		sysfs_init();
Packit Service 2a7015
		sysfs_initialized = 1;
Packit Service 2a7015
	}
Packit Service 2a7015
	increase_max_files();
Packit Service 2a7015
	if (idbm_init(NULL)) {
Packit Service 2a7015
		sysfs_cleanup();
Packit Service 2a7015
		free(context);
Packit Service 2a7015
		return NULL;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	iface_setup_host_bindings();
Packit Service 2a7015
Packit Service 2a7015
	return context;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
void libiscsi_cleanup(struct libiscsi_context *context)
Packit Service 2a7015
{
Packit Service 2a7015
	idbm_terminate();
Packit Service 2a7015
	free_transports();
Packit Service 2a7015
	sysfs_cleanup();
Packit Service 2a7015
	free(context);
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
static void free_iface_list(struct list_head *ifaces)
Packit Service 2a7015
{
Packit Service 2a7015
	struct iface_rec *iface, *tmp_iface;
Packit Service 2a7015
Packit Service 2a7015
	list_for_each_entry_safe(iface, tmp_iface, ifaces, list) {
Packit Service 2a7015
		list_del(&iface->list);
Packit Service 2a7015
		free(iface);
Packit Service 2a7015
	}
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
static void free_rec_list(struct list_head *rec_list)
Packit Service 2a7015
{
Packit Service 2a7015
	struct node_rec *rec, *tmp;
Packit Service 2a7015
	
Packit Service 2a7015
	list_for_each_entry_safe(rec, tmp, rec_list, list) {
Packit Service 2a7015
		list_del(&rec->list);
Packit Service 2a7015
		free(rec);
Packit Service 2a7015
	}
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_discover_sendtargets(struct libiscsi_context *context,
Packit Service 2a7015
	const char *address, int port,
Packit Service 2a7015
	const struct libiscsi_auth_info *auth_info,
Packit Service 2a7015
	int *nr_found, struct libiscsi_node **found_nodes)
Packit Service 2a7015
{
Packit Service 2a7015
	struct discovery_rec drec;
Packit Service 2a7015
	LIST_HEAD(bound_rec_list);
Packit Service 2a7015
	struct node_rec *rec;
Packit Service 2a7015
	int rc = 0, found = 0;
Packit Service 2a7015
Packit Service 2a7015
	INIT_LIST_HEAD(&bound_rec_list);
Packit Service 2a7015
Packit Service 2a7015
	if (nr_found)
Packit Service 2a7015
		*nr_found = 0;
Packit Service 2a7015
	if (found_nodes)
Packit Service 2a7015
		*found_nodes = NULL;
Packit Service 2a7015
Packit Service 2a7015
	CHECK(libiscsi_verify_auth_info(context, auth_info))
Packit Service 2a7015
Packit Service 2a7015
	/* Fill the drec struct with all needed info */
Packit Service 2a7015
	memset(&drec, 0, sizeof drec);
Packit Service 797ab3
	drec.iscsid_req_tmo = -1;
Packit Service 2a7015
	idbm_sendtargets_defaults(&drec.u.sendtargets);
Packit Service 2a7015
	drec.type = DISCOVERY_TYPE_SENDTARGETS;
Packit Service 2a7015
	strlcpy(drec.address, address, sizeof(drec.address));
Packit Service 2a7015
	drec.port = port ? port : ISCSI_LISTEN_PORT;
Packit Service 2a7015
	switch(auth_info ? auth_info->method : libiscsi_auth_none) {
Packit Service 2a7015
	case libiscsi_auth_chap:
Packit Service 2a7015
		drec.u.sendtargets.auth.authmethod = AUTH_METHOD_CHAP;
Packit Service 2a7015
		strlcpy(drec.u.sendtargets.auth.username,
Packit Service 2a7015
			auth_info->chap.username, AUTH_STR_MAX_LEN);
Packit Service 2a7015
		strlcpy((char *)drec.u.sendtargets.auth.password,
Packit Service 2a7015
			auth_info->chap.password, AUTH_STR_MAX_LEN);
Packit Service 2a7015
		drec.u.sendtargets.auth.password_length =
Packit Service 2a7015
			strlen((char *)drec.u.sendtargets.auth.password);
Packit Service 2a7015
		strlcpy(drec.u.sendtargets.auth.username_in,
Packit Service 2a7015
			auth_info->chap.reverse_username, AUTH_STR_MAX_LEN);
Packit Service 2a7015
		strlcpy((char *)drec.u.sendtargets.auth.password_in,
Packit Service 2a7015
			auth_info->chap.reverse_password, AUTH_STR_MAX_LEN);
Packit Service 2a7015
		drec.u.sendtargets.auth.password_in_length =
Packit Service 2a7015
			strlen((char *)drec.u.sendtargets.auth.password_in);
Packit Service 2a7015
		break;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	CHECK(idbm_add_discovery(&drec))
Packit Service 2a7015
Packit Service 2a7015
	CHECK(idbm_bind_ifaces_to_nodes(discovery_sendtargets,
Packit Service 2a7015
					&drec, NULL, &bound_rec_list))
Packit Service 2a7015
Packit Service 2a7015
	/* now add/update records */
Packit Service 2a7015
	list_for_each_entry(rec, &bound_rec_list, list) {
Packit Service 2a7015
		CHECK(idbm_add_node(rec, &drec, 1 /* overwrite */))
Packit Service 2a7015
		found++;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	if (nr_found)
Packit Service 2a7015
		*nr_found = found;
Packit Service 2a7015
Packit Service 2a7015
	if (found_nodes && found) {
Packit Service 2a7015
		*found_nodes = calloc(found, sizeof **found_nodes);
Packit Service 2a7015
		if (*found_nodes == NULL) {
Packit Service 2a7015
			snprintf(context->error_str,
Packit Service bed38a
				 sizeof(context->error_str),
Packit Service bed38a
				 "%s", strerror(ENOMEM));
Packit Service 2a7015
			rc = ENOMEM;
Packit Service 2a7015
			goto leave;
Packit Service 2a7015
		}
Packit Service 2a7015
		found = 0;
Packit Service 2a7015
		list_for_each_entry(rec, &bound_rec_list, list) {
Packit Service 2a7015
			strlcpy((*found_nodes)[found].name, rec->name,
Packit Service 2a7015
				 LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
			(*found_nodes)[found].tpgt = rec->tpgt;
Packit Service 2a7015
			strlcpy((*found_nodes)[found].address,
Packit Service 2a7015
				 rec->conn[0].address, NI_MAXHOST);
Packit Service 2a7015
			(*found_nodes)[found].port = rec->conn[0].port;
Packit Service 2a7015
			strlcpy((*found_nodes)[found].iface,
Packit Service 2a7015
				 rec->iface.name, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
			found++;
Packit Service 2a7015
		}
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
leave:
Packit Service 2a7015
	free_rec_list(&bound_rec_list);
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_discover_firmware(struct libiscsi_context *context,
Packit Service 2a7015
	int *nr_found, struct libiscsi_node **found_nodes)
Packit Service 2a7015
{
Packit Service 2a7015
	struct list_head targets, ifaces, rec_list;
Packit Service 2a7015
	discovery_rec_t drec;
Packit Service 2a7015
	int rc = 0;
Packit Service 2a7015
Packit Service 2a7015
	INIT_LIST_HEAD(&targets;;
Packit Service 2a7015
	INIT_LIST_HEAD(&ifaces);
Packit Service 2a7015
	INIT_LIST_HEAD(&rec_list);
Packit Service 2a7015
Packit Service 2a7015
	if (nr_found) {
Packit Service 2a7015
		*nr_found = 0;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	if (found_nodes) {
Packit Service 2a7015
		*found_nodes = NULL;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	rc = fw_get_targets(&targets;;
Packit Service 2a7015
	if (rc) {
Packit Service 2a7015
		log_error("%s: Could not get list of targets from firmware "
Packit Service 2a7015
			  "(err %d).\n", __func__, rc);
Packit Service 2a7015
		return rc;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	CHECK(iface_create_ifaces_from_boot_contexts(&ifaces, &targets));
Packit Service 2a7015
Packit Service 2a7015
	memset(&drec, 0, sizeof(drec));
Packit Service 797ab3
	drec.iscsid_req_tmo = -1;
Packit Service 2a7015
	drec.type = DISCOVERY_TYPE_FW;
Packit Service 2a7015
	rc = idbm_bind_ifaces_to_nodes(discovery_fw, &drec, &ifaces, &rec_list);
Packit Service 2a7015
	if (rc) {
Packit Service 2a7015
		log_error("%s: Could not determine target nodes from firmware "
Packit Service 2a7015
			  "(err %d).\n", __func__, rc);
Packit Service 2a7015
		goto leave;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	int node_count = 0;
Packit Service 2a7015
	struct list_head *pos;
Packit Service 2a7015
	list_for_each(pos, &rec_list) {
Packit Service 2a7015
		++node_count;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	struct libiscsi_node* new_nodes;
Packit Service 2a7015
	/* allocate enough space for all the nodes */
Packit Service 2a7015
	new_nodes = calloc(node_count, sizeof *new_nodes);
Packit Service 2a7015
	if (new_nodes == NULL) {
Packit Service 2a7015
		rc = ENOMEM;
Packit Service 2a7015
		log_error("%s: %s.\n", __func__, strerror(ENOMEM));
Packit Service 2a7015
		goto leave;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	struct node_rec *rec;
Packit Service 2a7015
	struct libiscsi_node *new_node = new_nodes;
Packit Service 2a7015
	/* in one loop, add nodes to idbm and create libiscsi_node entries */
Packit Service 2a7015
	list_for_each_entry(rec, &rec_list, list) {
Packit Service 2a7015
		CHECK(idbm_add_node(rec, NULL, 1 /* overwrite */));
Packit Service 2a7015
Packit Service 2a7015
		strlcpy(new_node->name, rec->name, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
		new_node->tpgt = rec->tpgt;
Packit Service 2a7015
		strlcpy(new_node->address, rec->conn[0].address, NI_MAXHOST);
Packit Service 2a7015
		new_node->port = rec->conn[0].port;
Packit Service 2a7015
		strlcpy(new_node->iface, rec->iface.name, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
Packit Service 2a7015
		++new_node;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	/* update output parameters */
Packit Service 2a7015
	if (nr_found) {
Packit Service 2a7015
		*nr_found = node_count;
Packit Service 2a7015
	}
Packit Service 2a7015
	if (found_nodes) {
Packit Service 2a7015
		*found_nodes = new_nodes;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
leave:
Packit Service 2a7015
	fw_free_targets(&targets;;
Packit Service 2a7015
Packit Service 2a7015
	free_iface_list(&ifaces);
Packit Service 2a7015
	free_rec_list(&rec_list);
Packit Service 2a7015
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_verify_auth_info(struct libiscsi_context *context,
Packit Service 2a7015
	const struct libiscsi_auth_info *auth_info)
Packit Service 2a7015
{
Packit Service 2a7015
	switch(auth_info ? auth_info->method : libiscsi_auth_none) {
Packit Service 2a7015
	case libiscsi_auth_none:
Packit Service 2a7015
		break;
Packit Service 2a7015
	case libiscsi_auth_chap:
Packit Service 2a7015
		if (!auth_info->chap.username[0]) {
Packit Service 2a7015
			strcpy(context->error_str, "Empty username");
Packit Service 2a7015
			return EINVAL;
Packit Service 2a7015
		}
Packit Service 2a7015
		if (!auth_info->chap.password[0]) {
Packit Service 2a7015
			strcpy(context->error_str, "Empty password");
Packit Service 2a7015
			return EINVAL;
Packit Service 2a7015
		}
Packit Service 2a7015
		if (auth_info->chap.reverse_username[0] &&
Packit Service 2a7015
		    !auth_info->chap.reverse_password[0]) {
Packit Service 2a7015
			strcpy(context->error_str, "Empty reverse password");
Packit Service 2a7015
		    	return EINVAL;
Packit Service 2a7015
		}
Packit Service 2a7015
		break;
Packit Service 2a7015
	default:
Packit Service 2a7015
		sprintf(context->error_str,
Packit Service 2a7015
			"Invalid authentication method: %d",
Packit Service 2a7015
			(int)auth_info->method);
Packit Service 2a7015
		return EINVAL;
Packit Service 2a7015
	}
Packit Service 2a7015
	return 0;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_node_set_auth(struct libiscsi_context *context,
Packit Service 2a7015
    const struct libiscsi_node *node,
Packit Service 2a7015
    const struct libiscsi_auth_info *auth_info)
Packit Service 2a7015
{
Packit Service 2a7015
	int rc = 0;
Packit Service 2a7015
Packit Service 2a7015
	CHECK(libiscsi_verify_auth_info(context, auth_info))
Packit Service 2a7015
Packit Service 2a7015
	switch(auth_info ? auth_info->method : libiscsi_auth_none) {
Packit Service 2a7015
	case libiscsi_auth_none:
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.authmethod", "None"))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username", ""))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password", ""))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username_in", ""))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password_in", ""))
Packit Service 2a7015
		break;
Packit Service 2a7015
Packit Service 2a7015
	case libiscsi_auth_chap:
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.authmethod", "CHAP"))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username",
Packit Service 2a7015
			auth_info->chap.username))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password",
Packit Service 2a7015
			auth_info->chap.password))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username_in",
Packit Service 2a7015
			auth_info->chap.reverse_username))
Packit Service 2a7015
		CHECK(libiscsi_node_set_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password_in",
Packit Service 2a7015
			auth_info->chap.reverse_password))
Packit Service 2a7015
		break;
Packit Service 2a7015
	}
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_node_get_auth(struct libiscsi_context *context,
Packit Service 2a7015
    const struct libiscsi_node *node,
Packit Service 2a7015
    struct libiscsi_auth_info *auth_info)
Packit Service 2a7015
{
Packit Service 2a7015
	int rc = 0;
Packit Service 2a7015
	char value[LIBISCSI_VALUE_MAXLEN];
Packit Service 2a7015
Packit Service 2a7015
	memset(auth_info, 0, sizeof *auth_info);
Packit Service 2a7015
Packit Service 2a7015
	CHECK(libiscsi_node_get_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.authmethod", value))
Packit Service 2a7015
Packit Service 2a7015
	if (!strcmp(value, "None")) {
Packit Service 2a7015
		auth_info->method = libiscsi_auth_none;
Packit Service 2a7015
	} else if (!strcmp(value, "CHAP")) {
Packit Service 2a7015
		auth_info->method = libiscsi_auth_chap;
Packit Service 2a7015
		CHECK(libiscsi_node_get_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username",
Packit Service 2a7015
			auth_info->chap.username))
Packit Service 2a7015
		CHECK(libiscsi_node_get_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password",
Packit Service 2a7015
			auth_info->chap.password))
Packit Service 2a7015
		CHECK(libiscsi_node_get_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.username_in",
Packit Service 2a7015
			auth_info->chap.reverse_username))
Packit Service 2a7015
		CHECK(libiscsi_node_get_parameter(context, node,
Packit Service 2a7015
			"node.session.auth.password_in",
Packit Service 2a7015
			auth_info->chap.reverse_password))
Packit Service 2a7015
	} else {
Packit Service 2a7015
		snprintf(context->error_str, sizeof(context->error_str),
Packit Service 2a7015
			 "unknown authentication method: %s", value);
Packit Service 2a7015
		rc = EINVAL;
Packit Service 2a7015
	}
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
static void node_to_rec(const struct libiscsi_node *node,
Packit Service 2a7015
	struct node_rec *rec)
Packit Service 2a7015
{
Packit Service 2a7015
	memset(rec, 0, sizeof *rec);
Packit Service 2a7015
	idbm_node_setup_defaults(rec);
Packit Service 2a7015
	strlcpy(rec->name, node->name, TARGET_NAME_MAXLEN);
Packit Service 2a7015
	rec->tpgt = node->tpgt;
Packit Service 2a7015
	strlcpy(rec->conn[0].address, node->address, NI_MAXHOST);
Packit Service 2a7015
	rec->conn[0].port = node->port;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int login_helper(void *data, node_rec_t *rec)
Packit Service 2a7015
{
Packit Service 2a7015
	char *iface = (char*)data;
Packit Service 2a7015
	if (strcmp(iface, rec->iface.name))
Packit Service 2a7015
		/* different iface, skip it */
Packit Service 2a7015
		return -1;
Packit Service 2a7015
Packit Service 2a7015
	int rc = iscsid_req_by_rec(MGMT_IPC_SESSION_LOGIN, rec);
Packit Service 2a7015
	if (rc) {
Packit Service 2a7015
		iscsi_err_print_msg(rc);
Packit Service 2a7015
		rc = ENOTCONN;
Packit Service 2a7015
	}
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_node_login(struct libiscsi_context *context,
Packit Service 2a7015
	const struct libiscsi_node *node)
Packit Service 2a7015
{
Packit Service 2a7015
	int nr_found = 0, rc;
Packit Service 2a7015
Packit Service 2a7015
	CHECK(idbm_for_each_iface(&nr_found, (void*)node->iface, login_helper,
Packit Service 2a7015
		(char *)node->name, node->tpgt,
Packit Service 99bacb
		(char *)node->address, node->port, false))
Packit Service 2a7015
	if (nr_found == 0) {
Packit Service 2a7015
		strcpy(context->error_str, "No such node");
Packit Service 2a7015
		rc = ENODEV;
Packit Service 2a7015
	}
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
static int logout_helper(void *data, struct session_info *info)
Packit Service 2a7015
{
Packit Service 2a7015
	int rc;
Packit Service 2a7015
	struct node_rec *rec = data;
Packit Service 2a7015
Packit Service 2a7015
	if (!iscsi_match_session(rec, info))
Packit Service 2a7015
		/* Tell iscsi_sysfs_for_each_session this session was not a
Packit Service 2a7015
		   match so that it will not increase nr_found. */
Packit Service 2a7015
		return -1;
Packit Service 2a7015
Packit Service 2a7015
	rc = iscsid_req_by_sid(MGMT_IPC_SESSION_LOGOUT, info->sid);
Packit Service 2a7015
	if (rc) {
Packit Service 2a7015
		iscsi_err_print_msg(rc);
Packit Service 2a7015
		rc = EIO;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_node_logout(struct libiscsi_context *context,
Packit Service 2a7015
	const struct libiscsi_node *node)
Packit Service 2a7015
{
Packit Service 2a7015
	int nr_found = 0, rc;
Packit Service 2a7015
	struct node_rec rec;
Packit Service 2a7015
Packit Service 2a7015
	node_to_rec(node, &rec);
Packit Service 2a7015
	CHECK(iscsi_sysfs_for_each_session(&rec, &nr_found, logout_helper,0))
Packit Service 2a7015
	if (nr_found == 0) {
Packit Service 2a7015
		strcpy(context->error_str, "No matching session");
Packit Service 2a7015
		rc = ENODEV;
Packit Service 2a7015
	}
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 6efcfa
struct libiscsi_session_array {
Packit Service 6efcfa
	int cnt;
Packit Service 6efcfa
	int size;
Packit Service 6efcfa
	struct libiscsi_session_info *data;
Packit Service 6efcfa
};
Packit Service 6efcfa
Packit Service 6efcfa
static void libiscsi_session_array_init(struct libiscsi_session_array *arr)
Packit Service 6efcfa
{
Packit Service 6efcfa
	arr->cnt = 0;
Packit Service 6efcfa
	arr->size = 0;
Packit Service 6efcfa
	arr->data = NULL;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
static int libiscsi_session_array_grow(struct libiscsi_session_array *arr)
Packit Service 6efcfa
{
Packit Service 6efcfa
	if (arr->size == 0)
Packit Service 6efcfa
		arr->size = 4;
Packit Service 6efcfa
	else
Packit Service 6efcfa
		arr->size *= 2;
Packit Service 6efcfa
Packit Service 6efcfa
	arr->data = (struct libiscsi_session_info *) realloc(
Packit Service 6efcfa
		arr->data,
Packit Service 6efcfa
		arr->size * sizeof(struct libiscsi_session_info));
Packit Service 6efcfa
Packit Service 6efcfa
	return arr->data ? 0 : 1;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
static int libiscsi_session_array_grow_ondemand(struct libiscsi_session_array *arr)
Packit Service 6efcfa
{
Packit Service 6efcfa
	if (arr->size == arr->cnt)
Packit Service 6efcfa
		return libiscsi_session_array_grow(arr);
Packit Service 6efcfa
	return 0;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
static int libiscsi_session_array_resize_precize(struct libiscsi_session_array *arr)
Packit Service 6efcfa
{
Packit Service 6efcfa
	arr->data = (struct libiscsi_session_info *) realloc(
Packit Service 6efcfa
		arr->data,
Packit Service 6efcfa
		arr->cnt * sizeof(struct libiscsi_session_info));
Packit Service 6efcfa
	arr->size = arr->cnt;
Packit Service 6efcfa
Packit Service 6efcfa
	return arr->data ? 0 : 1;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
static void copy_session_info_to_libiscsi_session_info(
Packit Service 6efcfa
	struct libiscsi_session_info *info,
Packit Service 6efcfa
	struct session_info *s_info)
Packit Service 6efcfa
{
Packit Service 6efcfa
	/* Copy session info to public struct. */
Packit Service 6efcfa
	info->sid = s_info->sid;
Packit Service 6efcfa
	/* Timeouts */
Packit Service 6efcfa
	memcpy(&info->tmo, &s_info->tmo, sizeof(struct libiscsi_session_timeout));
Packit Service 6efcfa
	/* CHAP authentication information */
Packit Service 6efcfa
	memcpy(&info->chap, &s_info->chap, sizeof(struct libiscsi_chap_auth_info));
Packit Service 6efcfa
	/* Target information */
Packit Service 6efcfa
	strncpy(info->targetname, s_info->targetname, LIBISCSI_VALUE_MAXLEN);
Packit Service 6efcfa
	strncpy(info->address, s_info->address, NI_MAXHOST);
Packit Service 6efcfa
	strncpy(info->persistent_address, s_info->persistent_address, NI_MAXHOST);
Packit Service 6efcfa
	info->tpgt = s_info->tpgt;
Packit Service 6efcfa
	info->persistent_port = s_info->persistent_port;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
static int get_sessions_helper(void *data, struct session_info *s_info)
Packit Service 6efcfa
{
Packit Service 6efcfa
	struct libiscsi_session_array *arr = (struct libiscsi_session_array *) data;
Packit Service 6efcfa
Packit Service 6efcfa
	if (libiscsi_session_array_grow_ondemand(arr) != 0)
Packit Service 6efcfa
		return 1;
Packit Service 6efcfa
Packit Service 6efcfa
	copy_session_info_to_libiscsi_session_info(&arr->data[arr->cnt++], s_info);
Packit Service 6efcfa
Packit Service 6efcfa
	return 0;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
int libiscsi_get_session_infos(struct libiscsi_context *context,
Packit Service 6efcfa
	struct libiscsi_session_info **infos,
Packit Service 6efcfa
	int *nr_sessions)
Packit Service 6efcfa
{
Packit Service 6efcfa
	int rc = 0;
Packit Service 6efcfa
	int nr_found = 0;
Packit Service 6efcfa
	struct libiscsi_session_array arr;
Packit Service 6efcfa
Packit Service 6efcfa
	if (!context || !infos || !nr_sessions)
Packit Service 6efcfa
		return 1;
Packit Service 6efcfa
Packit Service 6efcfa
	libiscsi_session_array_init(&arr;;
Packit Service 6efcfa
Packit Service 6efcfa
	rc = iscsi_sysfs_for_each_session((void *) &arr, &nr_found,
Packit Service 6efcfa
		get_sessions_helper, 0);
Packit Service 6efcfa
	if (rc != 0 || nr_found == 0) {
Packit Service 6efcfa
		strcpy(context->error_str, "No matching session");
Packit Service 6efcfa
		return ENODEV;
Packit Service 6efcfa
	}
Packit Service 6efcfa
Packit Service 6efcfa
	if (libiscsi_session_array_resize_precize(&arr) != 0) {
Packit Service 6efcfa
		strcpy(context->error_str, "Can't allocate memory for session infos");
Packit Service 6efcfa
		return ENOMEM;
Packit Service 6efcfa
	}
Packit Service 6efcfa
Packit Service 6efcfa
	*infos = arr.data;
Packit Service 6efcfa
	*nr_sessions = nr_found;
Packit Service 6efcfa
Packit Service 6efcfa
	return 0;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 6efcfa
int libiscsi_get_session_info_by_id(struct libiscsi_context *context,
Packit Service 6efcfa
	struct libiscsi_session_info *info,
Packit Service 6efcfa
	const char *session)
Packit Service 6efcfa
{
Packit Service 6efcfa
	struct session_info s_info;
Packit Service 6efcfa
Packit Service 6efcfa
	if (!context || !info || !session)
Packit Service 6efcfa
		return 1;
Packit Service 6efcfa
Packit Service 6efcfa
	if (iscsi_sysfs_get_sessioninfo_by_id(&s_info, (char*) session) != 0) {
Packit Service 6efcfa
		strcpy(context->error_str, "No matching session");
Packit Service 6efcfa
		return ENODEV;
Packit Service 6efcfa
	}
Packit Service 6efcfa
Packit Service 6efcfa
	copy_session_info_to_libiscsi_session_info(info, &s_info);
Packit Service 6efcfa
Packit Service 6efcfa
	return 0;
Packit Service 6efcfa
}
Packit Service 6efcfa
Packit Service 2a7015
int libiscsi_node_set_parameter(struct libiscsi_context *context,
Packit Service 2a7015
	const struct libiscsi_node *node,
Packit Service 2a7015
	const char *parameter, const char *value)
Packit Service 2a7015
{
Packit Service 2a7015
	int nr_found = 0, rc;
Packit Service 2a7015
	struct user_param *param;
Packit Service 2a7015
	struct list_head params;
Packit Service 2a7015
Packit Service 2a7015
	INIT_LIST_HEAD(&params);
Packit Service 2a7015
	param = idbm_alloc_user_param(parameter, value);
Packit Service 2a7015
	if (!param) {
Packit Service 2a7015
		rc = ENOMEM;
Packit Service 2a7015
		goto leave;
Packit Service 2a7015
	}
Packit Service 2a7015
	list_add_tail(&params, &param->list);
Packit Service 2a7015
Packit Service 2a7015
	CHECK(idbm_for_each_iface(&nr_found, &params, idbm_node_set_param,
Packit Service 2a7015
		(char *)node->name, node->tpgt,
Packit Service 99bacb
		(char *)node->address, node->port, false))
Packit Service 2a7015
	if (nr_found == 0) {
Packit Service 2a7015
		strcpy(context->error_str, "No such node");
Packit Service 2a7015
		rc = ENODEV;
Packit Service 2a7015
	}
Packit Service 2a7015
	free(param->name);
Packit Service 2a7015
	free(param);
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
static int get_parameter_helper(void *data, node_rec_t *rec)
Packit Service 2a7015
{
Packit Service 2a7015
	struct libiscsi_context *context = data;
Packit Service 2a7015
	recinfo_t *info;
Packit Service 2a7015
	int i;
Packit Service 2a7015
Packit Service 2a7015
	info = idbm_recinfo_alloc(MAX_KEYS);
Packit Service 2a7015
	if (!info) {
Packit Service 2a7015
		snprintf(context->error_str, sizeof(context->error_str),
Packit Service bed38a
			 "%s", strerror(ENOMEM));
Packit Service 2a7015
		return ENOMEM;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	idbm_recinfo_node(rec, info);
Packit Service 2a7015
Packit Service 2a7015
	for (i = 0; i < MAX_KEYS; i++) {
Packit Service 2a7015
		if (!info[i].visible)
Packit Service 2a7015
			continue;
Packit Service 2a7015
Packit Service 2a7015
		if (strcmp(context->parameter, info[i].name))
Packit Service 2a7015
			continue;
Packit Service 2a7015
Packit Service 2a7015
		strlcpy(context->value, info[i].value, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
		break;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	free(info);
Packit Service 2a7015
Packit Service 2a7015
	if (i == MAX_KEYS) {
Packit Service 2a7015
		strcpy(context->error_str, "No such parameter");
Packit Service 2a7015
		return EINVAL;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	return 0;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_node_get_parameter(struct libiscsi_context *context,
Packit Service 2a7015
	const struct libiscsi_node *node, const char *parameter, char *value)
Packit Service 2a7015
{
Packit Service 2a7015
	int nr_found = 0, rc = 0;
Packit Service 2a7015
Packit Service 2a7015
	context->parameter = parameter;
Packit Service 2a7015
	context->value = value;
Packit Service 2a7015
Packit Service 2a7015
	/* Note we assume there is only one interface, if not we will get
Packit Service 2a7015
	   the value from the last interface iterated over!
Packit Service 2a7015
	   This (multiple interfaces) can only happen if someone explicitly
Packit Service 2a7015
	   created ones using iscsiadm. Even then this should not be a problem
Packit Service 2a7015
	   as most settings should be the same independent of the iface. */
Packit Service 2a7015
	CHECK(idbm_for_each_iface(&nr_found, context, get_parameter_helper,
Packit Service 2a7015
		(char *)node->name, node->tpgt,
Packit Service 99bacb
		(char *)node->address, node->port, false))
Packit Service 2a7015
	if (nr_found == 0) {
Packit Service 2a7015
		strcpy(context->error_str, "No such node");
Packit Service 2a7015
		rc = ENODEV;
Packit Service 2a7015
	}
Packit Service 2a7015
leave:
Packit Service 2a7015
	return rc;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
const char *libiscsi_get_error_string(struct libiscsi_context *context)
Packit Service 2a7015
{
Packit Service 2a7015
	/* Sometimes the core open-iscsi code does not give us an error
Packit Service 2a7015
	   message */
Packit Service 2a7015
	if (!context->error_str[0])
Packit Service 2a7015
		return "Unknown error";
Packit Service 2a7015
Packit Service 2a7015
	return context->error_str;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
Packit Service 2a7015
/************************** Utility functions *******************************/
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_get_firmware_network_config(
Packit Service 2a7015
    struct libiscsi_network_config *config)
Packit Service 2a7015
{
Packit Service 2a7015
	struct boot_context fw_entry;
Packit Service 2a7015
Packit Service 2a7015
	if (!sysfs_initialized) {
Packit Service 2a7015
		sysfs_init();
Packit Service 2a7015
		sysfs_initialized = 1;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	memset(config, 0, sizeof *config);
Packit Service 2a7015
	memset(&fw_entry, 0, sizeof fw_entry);
Packit Service 2a7015
	if (fw_get_entry(&fw_entry))
Packit Service 2a7015
		return ENODEV;
Packit Service 2a7015
Packit Service 2a7015
	config->dhcp = strlen(fw_entry.dhcp) ? 1 : 0;
Packit Service 2a7015
	strlcpy(config->iface_name, fw_entry.iface, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->mac_address, fw_entry.mac, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->ip_address, fw_entry.ipaddr, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->netmask, fw_entry.mask, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->gateway, fw_entry.gateway, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->primary_dns, fw_entry.primary_dns, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	strlcpy(config->secondary_dns, fw_entry.secondary_dns, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	return 0;
Packit Service 2a7015
}
Packit Service 2a7015
Packit Service 2a7015
int libiscsi_get_firmware_initiator_name(char *initiatorname)
Packit Service 2a7015
{
Packit Service 2a7015
	struct boot_context fw_entry;
Packit Service 2a7015
Packit Service 2a7015
	if (!sysfs_initialized) {
Packit Service 2a7015
		sysfs_init();
Packit Service 2a7015
		sysfs_initialized = 1;
Packit Service 2a7015
	}
Packit Service 2a7015
Packit Service 2a7015
	memset(initiatorname, 0, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
	memset(&fw_entry, 0, sizeof fw_entry);
Packit Service 2a7015
	if (fw_get_entry(&fw_entry))
Packit Service 2a7015
		return ENODEV;
Packit Service 2a7015
Packit Service 2a7015
	strlcpy(initiatorname, fw_entry.initiatorname, LIBISCSI_VALUE_MAXLEN);
Packit Service 2a7015
Packit Service 2a7015
	return 0;
Packit Service 2a7015
}