Blame usr/initiator_common.c

Packit Service 646995
/*
Packit Service 646995
 * Common code for setting up discovery and normal sessions.
Packit Service 646995
 *
Packit Service 646995
 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
Packit Service 646995
 * Copyright (C) 2006 - 2009 Mike Christie
Packit Service 646995
 * Copyright (C) 2006 - 2009 Red Hat, Inc. All rights reserved.
Packit Service 646995
 * maintained by open-iscsi@googlegroups.com
Packit Service 646995
 *
Packit Service 646995
 * This program is free software; you can redistribute it and/or modify
Packit Service 646995
 * it under the terms of the GNU General Public License as published
Packit Service 646995
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 646995
 * (at your option) any later version.
Packit Service 646995
 *
Packit Service 646995
 * This program is distributed in the hope that it will be useful, but
Packit Service 646995
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 646995
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 646995
 * General Public License for more details.
Packit Service 646995
 *
Packit Service 646995
 * See the file COPYING included with this distribution for more details.
Packit Service 646995
 */
Packit Service 646995
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <dirent.h>
Packit Service 646995
#include <libmount/libmount.h>
Packit Service 646995
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "iscsid.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "iscsi_settings.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
#include "host.h"
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "iscsi_net_util.h"
Packit Service 646995
Packit Service 646995
struct iscsi_session *session_find_by_sid(uint32_t sid)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t;
Packit Service 646995
	struct iscsi_session *session;
Packit Service 646995
Packit Service 646995
	list_for_each_entry(t, &transports, list) {
Packit Service 646995
		list_for_each_entry(session, &t->sessions, list) {
Packit Service 646995
			if (session->id == sid)
Packit Service 646995
				return session;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
	return NULL;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static unsigned int align_32_down(unsigned int param)
Packit Service 646995
{
Packit Service 646995
	return param & ~0x3;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_setup_authentication(struct iscsi_session *session,
Packit Service 646995
			       struct iscsi_auth_config *auth_cfg)
Packit Service 646995
{
Packit Service 646995
	/* if we have any incoming credentials, we insist on authenticating
Packit Service 646995
	 * the target or not logging in at all
Packit Service 646995
	 */
Packit Service 646995
	if (auth_cfg->username_in[0] || auth_cfg->password_in_length) {
Packit Service 646995
		/* sanity check the config */
Packit Service 646995
		if (auth_cfg->password_length == 0) {
Packit Service 646995
			log_warning("CHAP configuration has incoming "
Packit Service 646995
				    "authentication credentials but has no "
Packit Service 646995
				    "outgoing credentials configured.");
Packit Service 646995
			return EINVAL;
Packit Service 646995
		}
Packit Service 646995
		session->bidirectional_auth = 1;
Packit Service 646995
	} else {
Packit Service 646995
		/* no or 1-way authentication */
Packit Service 646995
		session->bidirectional_auth = 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* copy in whatever credentials we have */
Packit Service 646995
	strlcpy(session->username, auth_cfg->username,
Packit Service 646995
		sizeof (session->username));
Packit Service 646995
	session->username[sizeof (session->username) - 1] = '\0';
Packit Service 646995
	if ((session->password_length = auth_cfg->password_length))
Packit Service 646995
		memcpy(session->password, auth_cfg->password,
Packit Service 646995
		       session->password_length);
Packit Service 646995
Packit Service 646995
	strlcpy(session->username_in, auth_cfg->username_in,
Packit Service 646995
		sizeof (session->username_in));
Packit Service 646995
	session->username_in[sizeof (session->username_in) - 1] = '\0';
Packit Service 646995
	if ((session->password_in_length =
Packit Service 646995
	     auth_cfg->password_in_length))
Packit Service 646995
		memcpy(session->password_in, auth_cfg->password_in,
Packit Service 646995
		       session->password_in_length);
Packit Service 646995
Packit Service 646995
	memcpy(session->chap_algs, auth_cfg->chap_algs, sizeof(auth_cfg->chap_algs));
Packit Service 646995
Packit Service 646995
	if (session->password_length || session->password_in_length) {
Packit Service 646995
		/* setup the auth buffers */
Packit Service 646995
		session->auth_buffers[0].address = &session->auth_client_block;
Packit Service 646995
		session->auth_buffers[0].length =
Packit Service 646995
		    sizeof (session->auth_client_block);
Packit Service 646995
		session->auth_buffers[1].address =
Packit Service 646995
		    &session->auth_recv_string_block;
Packit Service 646995
		session->auth_buffers[1].length =
Packit Service 646995
		    sizeof (session->auth_recv_string_block);
Packit Service 646995
Packit Service 646995
		session->auth_buffers[2].address =
Packit Service 646995
		    &session->auth_send_string_block;
Packit Service 646995
		session->auth_buffers[2].length =
Packit Service 646995
		    sizeof (session->auth_send_string_block);
Packit Service 646995
Packit Service 646995
		session->auth_buffers[3].address =
Packit Service 646995
		    &session->auth_recv_binary_block;
Packit Service 646995
		session->auth_buffers[3].length =
Packit Service 646995
		    sizeof (session->auth_recv_binary_block);
Packit Service 646995
Packit Service 646995
		session->auth_buffers[4].address =
Packit Service 646995
		    &session->auth_send_binary_block;
Packit Service 646995
		session->auth_buffers[4].length =
Packit Service 646995
		    sizeof (session->auth_send_binary_block);
Packit Service 646995
Packit Service 646995
		session->num_auth_buffers = 5;
Packit Service 646995
		log_debug(6, "authentication setup complete...");
Packit Service 646995
	} else {
Packit Service 646995
		session->num_auth_buffers = 0;
Packit Service 646995
		log_debug(6, "no authentication configured...");
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
void
Packit Service 646995
iscsi_copy_operational_params(struct iscsi_conn *conn,
Packit Service 646995
			struct iscsi_session_operational_config *session_conf,
Packit Service 646995
			struct iscsi_conn_operational_config *conn_conf)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_session *session = conn->session;
Packit Service 646995
	struct iscsi_transport *t = session->t;
Packit Service 646995
Packit Service 646995
	conn->hdrdgst_en = conn_conf->HeaderDigest;
Packit Service 646995
	conn->datadgst_en = conn_conf->DataDigest;
Packit Service 646995
Packit Service 646995
	conn->max_recv_dlength =
Packit Service 646995
			align_32_down(conn_conf->MaxRecvDataSegmentLength);
Packit Service 646995
	if (conn->max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
Packit Service 646995
	    conn->max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
Packit Service 646995
		log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be "
Packit Service 646995
			 "within %u and %u. Setting to %u",
Packit Service 646995
			  ISCSI_MIN_MAX_RECV_SEG_LEN,
Packit Service 646995
			  ISCSI_MAX_MAX_RECV_SEG_LEN,
Packit Service 646995
			  DEF_INI_MAX_RECV_SEG_LEN);
Packit Service 646995
		conn_conf->MaxRecvDataSegmentLength =
Packit Service 646995
						DEF_INI_MAX_RECV_SEG_LEN;
Packit Service 646995
		conn->max_recv_dlength = DEF_INI_MAX_RECV_SEG_LEN;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* zero indicates to use the target's value */
Packit Service 646995
	conn->max_xmit_dlength =
Packit Service 646995
			align_32_down(conn_conf->MaxXmitDataSegmentLength);
Packit Service 646995
	if (conn->max_xmit_dlength == 0)
Packit Service 646995
		conn->max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
Packit Service 646995
	if (conn->max_xmit_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
Packit Service 646995
	    conn->max_xmit_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
Packit Service 646995
		log_error("Invalid iscsi.MaxXmitDataSegmentLength. Must be "
Packit Service 646995
			 "within %u and %u. Setting to %u",
Packit Service 646995
			  ISCSI_MIN_MAX_RECV_SEG_LEN,
Packit Service 646995
			  ISCSI_MAX_MAX_RECV_SEG_LEN,
Packit Service 646995
			  DEF_INI_MAX_RECV_SEG_LEN);
Packit Service 646995
		conn_conf->MaxXmitDataSegmentLength =
Packit Service 646995
						DEF_INI_MAX_RECV_SEG_LEN;
Packit Service 646995
		conn->max_xmit_dlength = DEF_INI_MAX_RECV_SEG_LEN;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* session's operational parameters */
Packit Service 646995
	session->initial_r2t_en = session_conf->InitialR2T;
Packit Service 646995
	session->max_r2t = session_conf->MaxOutstandingR2T;
Packit Service 646995
	session->imm_data_en = session_conf->ImmediateData;
Packit Service 646995
	session->first_burst = align_32_down(session_conf->FirstBurstLength);
Packit Service 646995
	/*
Packit Service 646995
	 * some targets like netapp fail the login if sent bad first_burst
Packit Service 646995
	 * and max_burst lens, even when immediate data=no and
Packit Service 646995
	 * initial r2t = Yes, so we always check the user values.
Packit Service 646995
	 */
Packit Service 646995
	if (session->first_burst < ISCSI_MIN_FIRST_BURST_LEN ||
Packit Service 646995
	    session->first_burst > ISCSI_MAX_FIRST_BURST_LEN) {
Packit Service 646995
		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
Packit Service 646995
			 "within %u and %u. Setting to %u",
Packit Service 646995
			  session->first_burst,
Packit Service 646995
			  ISCSI_MIN_FIRST_BURST_LEN,
Packit Service 646995
			  ISCSI_MAX_FIRST_BURST_LEN,
Packit Service 646995
			  DEF_INI_FIRST_BURST_LEN);
Packit Service 646995
		session_conf->FirstBurstLength = DEF_INI_FIRST_BURST_LEN;
Packit Service 646995
		session->first_burst = DEF_INI_FIRST_BURST_LEN;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	session->max_burst = align_32_down(session_conf->MaxBurstLength);
Packit Service 646995
	if (session->max_burst < ISCSI_MIN_MAX_BURST_LEN ||
Packit Service 646995
	    session->max_burst > ISCSI_MAX_MAX_BURST_LEN) {
Packit Service 646995
		log_error("Invalid iscsi.MaxBurstLength of %u. Must be "
Packit Service 646995
			  "within %u and %u. Setting to %u",
Packit Service 646995
			   session->max_burst, ISCSI_MIN_MAX_BURST_LEN,
Packit Service 646995
			   ISCSI_MAX_MAX_BURST_LEN, DEF_INI_MAX_BURST_LEN);
Packit Service 646995
		session_conf->MaxBurstLength = DEF_INI_MAX_BURST_LEN;
Packit Service 646995
		session->max_burst = DEF_INI_MAX_BURST_LEN;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (session->first_burst > session->max_burst) {
Packit Service 646995
		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
Packit Service 646995
			  "less than iscsi.MaxBurstLength. Setting to %u",
Packit Service 646995
			   session->first_burst, session->max_burst);
Packit Service 646995
		session_conf->FirstBurstLength = session->max_burst;
Packit Service 646995
		session->first_burst = session->max_burst;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	session->def_time2wait = session_conf->DefaultTime2Wait;
Packit Service 646995
	session->def_time2retain = session_conf->DefaultTime2Retain;
Packit Service 646995
	session->erl = session_conf->ERL;
Packit Service 646995
Packit Service 646995
	if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) {
Packit Service 646995
		/*
Packit Service 646995
		 * Right now, we only support 8K max for kernel based
Packit Service 646995
		 * sendtargets discovery, because the recv pdu buffers are
Packit Service 646995
		 * limited to this size.
Packit Service 646995
		 */
Packit Service 646995
		if ((t->caps & CAP_TEXT_NEGO) &&
Packit Service 646995
		     conn->max_recv_dlength > ISCSI_DEF_MAX_RECV_SEG_LEN)
Packit Service 646995
			conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
Packit Service 646995
Packit Service 646995
		/* We do not support discovery sessions with digests */
Packit Service 646995
		conn->hdrdgst_en = ISCSI_DIGEST_NONE;
Packit Service 646995
		conn->datadgst_en = ISCSI_DIGEST_NONE;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (t->template->create_conn)
Packit Service 646995
		t->template->create_conn(conn);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port)
Packit Service 646995
{
Packit Service 646995
	char serv[NI_MAXSERV];
Packit Service 646995
Packit Service 646995
	sprintf(serv, "%d", port);
Packit Service 646995
	if (resolve_address(address, serv, &conn->saddr)) {
Packit Service 646995
		log_error("cannot resolve host name %s", address);
Packit Service 646995
		return ISCSI_ERR_TRANS;
Packit Service 646995
	}
Packit Service 646995
	conn->failback_saddr = conn->saddr;
Packit Service 646995
Packit Service 646995
	getnameinfo((struct sockaddr *)&conn->saddr, sizeof(conn->saddr),
Packit Service 646995
		    conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST);
Packit Service 646995
	log_debug(4, "resolved %s to %s", address, conn->host);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int host_set_param(struct iscsi_transport *t,
Packit Service 646995
		   uint32_t host_no, int param, char *value,
Packit Service 646995
		   int type)
Packit Service 646995
{
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	rc = ipc->set_host_param(t->handle, host_no, param, value, type);
Packit Service 646995
	/* 2.6.20 and below returns EINVAL */
Packit Service 646995
	if (rc && rc != -ENOSYS && rc != -EINVAL) {
Packit Service 646995
		log_error("can't set operational parameter %d for "
Packit Service 646995
			  "host %d, retcode %d (%d)", param, host_no,
Packit Service 646995
			  rc, errno);
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void print_param_value(enum iscsi_param param, void *value, int type)
Packit Service 646995
{
Packit Service 646995
	log_debug(3, "set operational parameter %d to:", param);
Packit Service 646995
Packit Service 646995
	if (type == ISCSI_STRING)
Packit Service 646995
		log_debug(3, "%s", value ? (char *)value : "NULL");
Packit Service 646995
	else
Packit Service 646995
		log_debug(3, "%u", *(uint32_t *)value);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define MAX_HOST_PARAMS 2
Packit Service 646995
Packit Service 646995
int iscsi_host_set_params(struct iscsi_session *session)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = session->t;
Packit Service 646995
	int i;
Packit Service 646995
	struct hostparam {
Packit Service 646995
		int param;
Packit Service 646995
		int type;
Packit Service 646995
		void *value;
Packit Service 646995
	} hosttbl[MAX_HOST_PARAMS] = {
Packit Service 646995
		{
Packit Service 646995
			.param = ISCSI_HOST_PARAM_NETDEV_NAME,
Packit Service 646995
			.value = session->nrec.iface.netdev,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_HOST_PARAM_HWADDRESS,
Packit Service 646995
			.value = session->nrec.iface.hwaddress,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
		},
Packit Service 646995
	};
Packit Service 646995
Packit Service 646995
	for (i = 0; i < MAX_HOST_PARAMS; i++) {
Packit Service 646995
		if (host_set_param(t, session->hostno,
Packit Service 646995
				   hosttbl[i].param, hosttbl[i].value,
Packit Service 646995
				   hosttbl[i].type)) {
Packit Service 646995
			return EPERM;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		print_param_value(hosttbl[i].param, hosttbl[i].value,
Packit Service 646995
				  hosttbl[i].type);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static inline void iscsi_session_clear_param(struct iscsi_session *session,
Packit Service 646995
					     int param)
Packit Service 646995
{
Packit Service 646995
	session->param_mask &= ~(1ULL << param);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
void iscsi_session_init_params(struct iscsi_session *session)
Packit Service 646995
{
Packit Service 646995
	session->param_mask = ~0ULL;
Packit Service 646995
	if (!(session->t->caps & CAP_MULTI_R2T))
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_MAX_R2T);
Packit Service 646995
	if (!(session->t->caps & CAP_HDRDGST))
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_HDRDGST_EN); 
Packit Service 646995
	if (!(session->t->caps & CAP_DATADGST))
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_DATADGST_EN); 
Packit Service 646995
	if (!(session->t->caps & CAP_MARKERS)) {
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_IFMARKER_EN);
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_OFMARKER_EN);
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define MAX_SESSION_NEG_PARAMS 16
Packit Service 646995
Packit Service 646995
int iscsi_session_set_neg_params(struct iscsi_conn *conn)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_session *session = conn->session;
Packit Service 646995
	int i, rc;
Packit Service 646995
	uint32_t zero = 0;
Packit Service 646995
	struct connparam {
Packit Service 646995
		int param;
Packit Service 646995
		int type;
Packit Service 646995
		void *value;
Packit Service 646995
		int conn_only;
Packit Service 646995
	} conntbl[MAX_SESSION_NEG_PARAMS] = {
Packit Service 646995
		{
Packit Service 646995
			.param = ISCSI_PARAM_MAX_RECV_DLENGTH,
Packit Service 646995
			.value = &conn->max_recv_dlength,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_MAX_XMIT_DLENGTH,
Packit Service 646995
			.value = &conn->max_xmit_dlength,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_HDRDGST_EN,
Packit Service 646995
			.value = &conn->hdrdgst_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_DATADGST_EN,
Packit Service 646995
			.value = &conn->datadgst_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_INITIAL_R2T_EN,
Packit Service 646995
			.value = &session->initial_r2t_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_MAX_R2T,
Packit Service 646995
			.value = &session->max_r2t,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_IMM_DATA_EN,
Packit Service 646995
			.value = &session->imm_data_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_FIRST_BURST,
Packit Service 646995
			.value = &session->first_burst,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_MAX_BURST,
Packit Service 646995
			.value = &session->max_burst,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PDU_INORDER_EN,
Packit Service 646995
			.value = &session->pdu_inorder_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param =ISCSI_PARAM_DATASEQ_INORDER_EN,
Packit Service 646995
			.value = &session->dataseq_inorder_en,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_ERL,
Packit Service 646995
			.value = &zero, /* FIXME: session->erl */
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_IFMARKER_EN,
Packit Service 646995
			.value = &zero,/* FIXME: session->ifmarker_en */
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_OFMARKER_EN,
Packit Service 646995
			.value = &zero,/* FIXME: session->ofmarker_en */
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_EXP_STATSN,
Packit Service 646995
			.value = &conn->exp_statsn,
Packit Service 646995
			.type = ISCSI_UINT,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_TPGT,
Packit Service 646995
			.value = &session->portal_group_tag,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		},
Packit Service 646995
	};
Packit Service 646995
Packit Service 646995
	iscsi_session_init_params(session);
Packit Service 646995
Packit Service 646995
	/* Entered full-feature phase! */
Packit Service 646995
	for (i = 0; i < MAX_SESSION_NEG_PARAMS; i++) {
Packit Service 646995
		if (conn->id != 0 && !conntbl[i].conn_only)
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		if (!(session->param_mask & (1ULL << conntbl[i].param)))
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		rc = ipc->set_param(session->t->handle, session->id,
Packit Service 646995
				   conn->id, conntbl[i].param, conntbl[i].value,
Packit Service 646995
				   conntbl[i].type);
Packit Service 646995
		if (rc && rc != -ENOSYS) {
Packit Service 646995
			log_error("can't set operational parameter %d for "
Packit Service 646995
				  "connection %d:%d, retcode %d (%d)",
Packit Service 646995
				  conntbl[i].param, session->id, conn->id,
Packit Service 646995
				  rc, errno);
Packit Service 646995
			return EPERM;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		print_param_value(conntbl[i].param, conntbl[i].value,
Packit Service 646995
				  conntbl[i].type);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define MAX_SESSION_PARAMS 20
Packit Service 646995
Packit Service 646995
int iscsi_session_set_params(struct iscsi_conn *conn)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_session *session = conn->session;
Packit Service 646995
	int i, rc;
Packit Service 646995
	struct connparam {
Packit Service 646995
		int param;
Packit Service 646995
		int type;
Packit Service 646995
		void *value;
Packit Service 646995
		int conn_only;
Packit Service 646995
	} conntbl[MAX_SESSION_PARAMS] = {
Packit Service 646995
		{
Packit Service 646995
			.param = ISCSI_PARAM_TARGET_NAME,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.value = session->target_name,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PERSISTENT_ADDRESS,
Packit Service 646995
			.value = session->nrec.conn[conn->id].address,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PERSISTENT_PORT,
Packit Service 646995
			.value = &session->nrec.conn[conn->id].port,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_SESS_RECOVERY_TMO,
Packit Service 646995
			.value = &session->replacement_timeout,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_USERNAME,
Packit Service 646995
			.value = session->username,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_USERNAME_IN,
Packit Service 646995
			.value = session->username_in,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PASSWORD,
Packit Service 646995
			.value = session->password,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PASSWORD_IN,
Packit Service 646995
			.value = session->password_in,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_FAST_ABORT,
Packit Service 646995
			.value = &session->fast_abort,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_ABORT_TMO,
Packit Service 646995
			.value = &session->abort_timeout,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_LU_RESET_TMO,
Packit Service 646995
			.value = &session->lu_reset_timeout,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_TGT_RESET_TMO,
Packit Service 646995
			.value = &session->tgt_reset_timeout,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_PING_TMO,
Packit Service 646995
			.value = &conn->noop_out_timeout,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_RECV_TMO,
Packit Service 646995
			.value = &conn->noop_out_interval,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 1,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_IFACE_NAME,
Packit Service 646995
			.value = session->nrec.iface.name,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_INITIATOR_NAME,
Packit Service 646995
			.value = session->initiator_name,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_BOOT_ROOT,
Packit Service 646995
			.value = session->nrec.session.boot_root,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_BOOT_NIC,
Packit Service 646995
			.value = session->nrec.session.boot_nic,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_BOOT_TARGET,
Packit Service 646995
			.value = session->nrec.session.boot_target,
Packit Service 646995
			.type = ISCSI_STRING,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		}, {
Packit Service 646995
			.param = ISCSI_PARAM_DISCOVERY_SESS,
Packit Service 646995
			.value = &session->type,
Packit Service 646995
			.type = ISCSI_INT,
Packit Service 646995
			.conn_only = 0,
Packit Service 646995
		},
Packit Service 646995
	};
Packit Service 646995
Packit Service 646995
	iscsi_session_init_params(session);
Packit Service 646995
Packit Service 646995
	/* some llds will send nops internally */
Packit Service 646995
	if (!iscsi_sysfs_session_supports_nop(session->id)) {
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_PING_TMO); 
Packit Service 646995
		iscsi_session_clear_param(session, ISCSI_PARAM_RECV_TMO);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* Entered full-feature phase! */
Packit Service 646995
	for (i = 0; i < MAX_SESSION_PARAMS; i++) {
Packit Service 646995
		if (conn->id != 0 && !conntbl[i].conn_only)
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		if (!(session->param_mask & (1ULL << conntbl[i].param)))
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		rc = ipc->set_param(session->t->handle, session->id,
Packit Service 646995
				   conn->id, conntbl[i].param, conntbl[i].value,
Packit Service 646995
				   conntbl[i].type);
Packit Service 646995
		if (rc && rc != -ENOSYS) {
Packit Service 646995
			log_error("can't set operational parameter %d for "
Packit Service 646995
				  "connection %d:%d, retcode %d (%d)",
Packit Service 646995
				  conntbl[i].param, session->id, conn->id,
Packit Service 646995
				  rc, errno);
Packit Service 646995
			return EPERM;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (rc == -ENOSYS) {
Packit Service 646995
			switch (conntbl[i].param) {
Packit Service 646995
			case ISCSI_PARAM_PING_TMO:
Packit Service 646995
				/*
Packit Service 646995
				 * older kernels may not support nops
Packit Service 646995
				 * in kernel
Packit Service 646995
				 */
Packit Service 646995
				conn->userspace_nop = 1;
Packit Service 646995
				break;
Packit Service 646995
#if 0
Packit Service 646995
TODO handle this
Packit Service 646995
			case ISCSI_PARAM_INITIATOR_NAME:
Packit Service 646995
				/* use host level one instead */
Packit Service 646995
				hosttbl[ISCSI_HOST_PARAM_INITIATOR_NAME].set = 1;
Packit Service 646995
				break;
Packit Service 646995
#endif
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		print_param_value(conntbl[i].param, conntbl[i].value,
Packit Service 646995
				  conntbl[i].type);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_set_net_config(struct iscsi_transport *t, iscsi_session_t *session,
Packit Service 646995
			 struct iface_rec *iface)
Packit Service 646995
{
Packit Service 646995
	if (t->template->set_net_config) {
Packit Service 646995
		/* uip needs the netdev name */
Packit Service 646995
		struct host_info hinfo;
Packit Service 646995
		int hostno, rc;
Packit Service 646995
Packit Service 646995
		/* this assumes that the netdev or hw address is going to be
Packit Service 646995
		   set */
Packit Service 646995
		hostno = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
Packit Service 646995
		if (rc) {
Packit Service 646995
			log_debug(4, "Couldn't get host no.");
Packit Service 646995
			return rc;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		/* uip needs the netdev name */
Packit Service 646995
		if (!strlen(iface->netdev)) {
Packit Service 646995
			memset(&hinfo, 0, sizeof(hinfo));
Packit Service 646995
			hinfo.host_no = hostno;
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
		return t->template->set_net_config(t, iface, session);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_host_set_net_params(struct iface_rec *iface,
Packit Service 646995
			      struct iscsi_session *session)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport *t = session->t;
Packit Service 646995
	int rc = 0;
Packit Service 646995
	char *netdev;
Packit Service 646995
	struct host_info hinfo;
Packit Service 646995
Packit Service 646995
	log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, "
Packit Service 646995
		  "transport %s.",
Packit Service 646995
		  iface->name, iface->netdev, iface->ipaddress,
Packit Service 646995
		  iface->hwaddress, iface->transport_name);
Packit Service 646995
Packit Service 646995
	if (!t->template->set_host_ip)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	/* if we need to set the ip addr then set all the iface net settings */
Packit Service 646995
	if (!iface_is_bound_by_ipaddr(iface)) {
Packit Service 646995
		if (t->template->set_host_ip == SET_HOST_IP_REQ) {
Packit Service 646995
			log_warning("Please set the iface.ipaddress for iface "
Packit Service 646995
				    "%s, then retry the login command.",
Packit Service 646995
				    iface->name);
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		} else if (t->template->set_host_ip == SET_HOST_IP_OPT) {
Packit Service 646995
			log_info("Optional iface.ipaddress for iface %s "
Packit Service 646995
				 "not set.", iface->name);
Packit Service 646995
			return 0;
Packit Service 646995
		} else {
Packit Service 646995
			return ISCSI_ERR_INVAL;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* these type of drivers need the netdev upd */
Packit Service 646995
	if (strlen(iface->netdev))
Packit Service 646995
		netdev = iface->netdev;
Packit Service 646995
	else {
Packit Service 646995
		memset(&hinfo, 0, sizeof(hinfo));
Packit Service 646995
		hinfo.host_no = session->hostno;
Packit Service 646995
		iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
Packit Service 646995
Packit Service 646995
		netdev = hinfo.iface.netdev;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!t->template->no_netdev && net_ifup_netdev(netdev))
Packit Service 646995
		log_warning("Could not brining up netdev %s. Try running "
Packit Service 646995
			    "'ifup %s' first if login fails.", netdev, netdev);
Packit Service 646995
Packit Service 646995
	rc = iscsi_set_net_config(t, session, iface);
Packit Service 646995
	if (rc != 0)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	rc = host_set_param(t, session->hostno,
Packit Service 646995
			    ISCSI_HOST_PARAM_IPADDRESS,
Packit Service 646995
			    iface->ipaddress, ISCSI_STRING);
Packit Service 646995
	if (rc)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	if (iface_is_bound_by_netdev(iface)) {
Packit Service 646995
		rc = host_set_param(t, session->hostno,
Packit Service 646995
				    ISCSI_HOST_PARAM_NETDEV_NAME,
Packit Service 646995
				    iface->netdev, ISCSI_STRING);
Packit Service 646995
		if (rc)
Packit Service 646995
			return rc;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (iface_is_bound_by_hwaddr(iface)) {
Packit Service 646995
		rc = host_set_param(t, session->hostno,
Packit Service 646995
				    ISCSI_HOST_PARAM_HWADDRESS,
Packit Service 646995
				    iface->hwaddress, ISCSI_STRING);
Packit Service 646995
		if (rc)
Packit Service 646995
			return rc;
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}