/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*
* iSCSI Software Initiator
*/
/*
* Framework interface routines for iSCSI
*/
#include "iscsi.h" /* main header */
#include "persistent.h"
#include "iscsi_targetparam.h"
#include <sys/socketvar.h>
#include <sys/bootprops.h>
extern ib_boot_prop_t *iscsiboot_prop;
/*
* iscsi_ioctl_copyin -
*/
void *
{
}
return (data);
}
/*
* iscsi_ioctl_copyout -
*/
int
{
int rtn;
rtn = 0;
}
return (rtn);
}
/*
* iscsi_conn_list_get_copyin -
*/
{
sizeof (iscsi_if_conn_t));
}
KM_SLEEP);
}
}
return (cl);
}
/*
* iscsi_conn_list_get_copyout -
*/
int
int mode)
{
int rtn;
}
rtn = 0;
}
return (rtn);
}
/*
* iscsi_conn_oid_list_get -
*/
{
/* Let's check the version. */
return (B_FALSE);
}
/* We preinitialize the output connection counter. */
cl->cl_out_cnt = 0;
/* The list of sessions is walked holding the HBA mutex. */
/*
* Check to see if oid references a target-param oid. If so,
* find the associated session oid before getting lu list.
*/
break;
}
}
} else {
}
/* return connections for NORMAL sessions only */
/*
* The list of connections is walked holding
* the session mutex.
*/
if (icp->conn_state ==
/* There's still room. */
cnx =
cl->cl_out_cnt];
}
++cl->cl_out_cnt;
}
}
/*
* We got here because it was the only session
* we were looking for. We can exit now.
*/
break;
}
}
}
return (B_TRUE);
}
/*
* iscsi_ioctl_conn_props_get -
*/
{
/* Let's check the version. */
return (B_FALSE);
}
/* Let's find the session. */
return (B_FALSE);
}
idm_conn =
/* Local Address */
sizeof (struct sockaddr_in));
} else {
sizeof (struct sockaddr_in6));
}
/* Peer Address */
sizeof (struct sockaddr_in));
} else {
sizeof (struct sockaddr_in6));
}
sizeof (icp->conn_params));
}
break;
}
}
return (rtn);
}
/*
* iscsi_ioctl_sendtgts_get - 0 on success; errno on failure
*
*/
int
{
char *data;
/* create discovery session */
return (1);
}
/* create connection */
if (!ISCSI_SUCCESS(status)) {
(void) iscsi_sess_destroy(isp);
return (1);
}
/* start login */
if (status == ISCSI_STATUS_SUCCESS) {
sizeof (ISCSI_SENDTGTS_REQ_STR));
/* execute SendTargets operation */
sizeof (ISCSI_SENDTGTS_REQ_STR), &rx_data_len);
/* check if allocated buffer is too small for response */
if (status == ISCSI_STATUS_DATA_OVERFLOW) {
goto retry_sendtgts;
}
if (ISCSI_SUCCESS(status)) {
rx_data_len, stl);
if (ISCSI_SUCCESS(status)) {
rtn = 0;
}
} else {
}
} else {
}
/*
* check if session is still alive. It may have been destroyed
* by a driver unload
*/
(void) iscsi_sess_destroy(isp);
}
return (rtn);
}
/*
* iscsi_create_sendtgts_list - Based upon the given data, build a
* linked list of SendTarget information. The data passed into this
* function is expected to be the data portion(s) of SendTarget text
* response.
*/
static iscsi_status_t
{
int error_num;
/* initialize number of targets found */
stl->stl_out_cnt = 0;
if (data_len == 0)
return (ISCSI_STATUS_SUCCESS);
/* check if this is first targetname */
stl->stl_out_cnt++;
}
/*
* continue processing the data so that
* the total number of targets are known
* and the caller can retry with the correct
* number of entries in the list
*/
continue;
}
/*
* This entry will use the IP address and port
* that was passed into this routine. If the next
* line that we receive is a TargetAddress we will
* know to modify this entry with the new IP address,
* port and portal group tag. If this state flag
* is not set we'll just create a new entry using
* only the previous entries targetname.
*/
sizeof (struct in_addr);
sizeof (struct in_addr));
} else {
sizeof (struct in6_addr);
sizeof (struct in6_addr));
}
strlen(TARGETADDRESS)) == 0) {
char *in_str,
*tmp_buf,
*addr_str,
*port_str,
*tpgt_str;
int type,
long result;
/*
* If TARGETADDRESS is first line a SendTarget response
* (i.e. no TARGETNAME lines preceding), treat as
* an error. To check this an assumption is made that
* at least one sendtarget_entry_t should exist prior
* to entering this code.
*/
"TARGETADDRESS first");
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
/*
* If we can't find an '=' then the sendtargets
* response if invalid per spec. Return empty list.
*/
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
/* move past the '=' */
in_str++;
/* Copy addr, port, and tpgt into temporary buffer */
/*
* Parse the addr, port, and tpgt from
* sendtarget response
*/
/* Unable to extract addr */
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
/* Now convert string addr to binary */
if (!hptr) {
/* Unable to get valid address */
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
/* Check if space for response */
if (targetname_added == B_FALSE) {
stl->stl_out_cnt++;
/*
* continue processing the data so that
* the total number of targets are
* known and the caller can retry with
* the correct number of entries in
* the list
*/
continue;
}
}
} else {
}
} else {
"TPGT not specified");
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
/*
* Any other string besides an empty string
* is a protocol error
*/
"unexpected response");
return (ISCSI_STATUS_PROTOCOL_ERROR);
}
}
/*
* If target found increment out count one more time because
* this is the total number of entries in the list not an index
* like it was used above
*/
stl->stl_out_cnt++;
}
return (ISCSI_STATUS_SUCCESS);
}
/*
* iscsi_set_param - This function is a helper to ISCSI_SET_PARAM
* IOCTL
*/
int
{
int rtn = 0;
/*
* Use get param to get the min, max and increment values for the
* given parameter so validation can be done on the new value.
*/
if (rtn != 0) {
return (rtn);
}
return (rtn);
}
}
/*
* Boolean parameters
*/
break;
break;
break;
break;
/*
* Integer parameters
*/
break;
break;
break;
break;
break;
} else {
}
break;
} else {
}
break;
/*
* Integer parameters which currently are unsettable
*/
break;
default:
break;
}
return (rtn);
}
int
{
int rtn = 0;
/* handle special case for Initiator name */
if (persist) {
char *name;
/* save off old Initiator name */
(void) persistent_initiator_name_set(
/*
* check to see if we have login param,
* chap param, or authentication params
* loaded in persistent that we have to change
* the name of
*/
/* checking login params */
KM_SLEEP);
}
}
}
/* check chap params */
KM_SLEEP);
/*
* Update CHAP user name only if the
* original username was set to the
* initiator node name. Otherwise
* leave it the way it is.
*/
int userSize;
userSize =
if (strncmp((char *)
== 0) {
userSize);
bcopy((char *)
strlen((char *)
chap->c_user_len =
strlen((char *)
}
}
}
}
/* check authentication params */
KM_SLEEP);
auth);
}
}
}
}
}
if (persist) {
(void) persistent_alias_name_set(
}
} else {
/* switch login based if looking for initiator params */
/* initiator */
} else {
/* session */
pp = (persistent_param_t *)
}
if (rtn == 0) {
}
}
}
/*
* Here may have multiple sessions with different
* tpgt values. So it is needed to loop through
* the sessions and update all sessions.
*/
if (rtn == 0) {
if (iscsiboot_prop &&
/*
* MPxIO is enabled so capable
* of changing. All changes
* will be applied later,
* after this function
*/
continue;
}
(char *)name,
ISCSI_MAX_NAME_LEN) == 0) {
}
}
}
} /* end of 'else' */
pp = (persistent_param_t *)
}
}
/*
* if initiator parameter set, modify all associated
* sessions that don't already have the parameter
* overriden
*/
ilg = (iscsi_param_get_t *)
if (rtn != 0) {
break;
}
if (iscsiboot_prop &&
/*
* MPxIO is enabled so capable
* of changing. Changes will
* be applied later, right
* after this function
*/
continue;
}
/*
* Notify the session that
* the login parameters have
* changed.
*/
}
}
}
}
return (rtn);
}
int
{
int rtn;
char *name;
/*
* If we're just attempting to get the target properties don't
* create the session if it doesn't already exist. If we setting
* the property then create the session if needed because we'll
* most likely see an ISCSI_LOGIN in a few.
*/
/*
* If the oid does represent a session check to see
* if it is a target oid. If so, return the target's
* associated session.
*/
if (rtn != 0) {
}
/*
* If rtn is zero then we have found an existing session.
* Use the session name for database lookup. If rtn is
* non-zero then create a targetparam object and use
* its name for database lookup.
*/
if (rtn == 0) {
} else {
}
return (rtn);
}
rtn = 0;
if (cmd == ISCSI_TARGET_PROPS_GET) {
/*
* If isp is not null get the session's parameters, otherwise
* the get is for a target-param object so defaults need to
* be returned.
*/
int conn_count = 0;
if (icp->conn_state ==
conn_count++;
}
}
} else {
ipp->p_num_of_connections = 0;
}
} else {
return (rtn);
}
/* ISCSI_TARGET_PROPS_SET */
/*
* only update if new, otherwise could clear out alias
* if just updating the discovery.
*/
if (ipp->p_alias_len != 0) {
ipp->p_alias_len);
}
}
return (rtn);
}
/*
* iscsi_ioctl_get_config_sess - gets configured session information
*
* This function is an ioctl helper function to get the
* configured session information from the persistent store.
*/
int
{
/* Get the matching iscsi node name for the oid */
/* initiator name */
} else {
/* target name */
/* invalid node name */
return (EINVAL);
}
}
/* get configured session information */
/*
* There might not be anything in the database yet. If
* this is a request for the target check the initiator
* value. If neither is set return the default value.
*/
/*
* No initiator value is set.
* Return the defaults.
*/
}
} else {
}
}
return (0);
}
/*
* iscsi_ioctl_set_config_sess - sets configured session information
*
* This function is an ioctl helper function to set the
* configured session information in the persistent store.
* In addition it will notify any active sessions of the
* changed so this can update binding information. It
* will also destroy sessions that were removed and add
* new sessions.
*/
int
{
/* check range infomration */
/* invalid range information */
return (EINVAL);
}
} else {
/* get target name */
/* invalid node name */
return (EINVAL);
}
}
/* store the new information */
/* failed to store new information */
return (EINVAL);
}
/* notify existing sessions of change */
ISCSI_MAX_NAME_LEN) == 0)) {
/*
* If this sessions least signficant byte
* of the isid is less than or equal to
* the the number of configured sessions
* then we need to tear down this session.
*/
/* First attempt to destory the session */
} else {
/*
* If we can't destroy it then
* atleast poke it to disconnect
* it.
*/
}
} else {
}
} else {
}
}
/*
* The number of targets has changed. Since we don't expect
* this to be a common operation lets keep the code simple and
* just use a slightly larger hammer and poke discovery. This
* force the reevaulation of this target and all other targets.
*/
/* lock so only one config operation occrs */
return (0);
}
int
{
int param_id = 0;
} else {
/* get target name */
/* invalid node name */
return (EINVAL);
}
}
KM_SLEEP);
/* use default value */
}
switch (param_id) {
break;
break;
break;
default:
break;
}
if (persistent_set_tunable_param((char *)name,
return (EINVAL);
}
sizeof (iscsi_tunable_params_t));
}
continue;
}
sizeof (iscsi_tunable_params_t));
} else {
/*
* this session connected target
* tunable parameters not set,
* use initiator's default
*/
sizeof (iscsi_tunable_params_t));
}
}
}
return (0);
}