iscsit_text.c revision 59927d313a821b7f3822314ed16fc0a44c128431
/*
* 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
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
#include <sys/stmf_ioctl.h>
#include "iscsit_isns.h"
#include "iscsit.h"
void
/*
* The kernel inet_ntop() function formats ipv4 address fields with
* leading zeros which the win2k initiator interprets as octal.
*/
static void
{
unsigned char *p = (unsigned char *) in;
}
static void
{
/*
* Set the target task tag. The value will be zero when
* the connection is created. Increment it and wrap it
* back to one if we hit the reserved value.
*
* The TTT is fabricated since there is no real task associated
* with a text request. The idm task range is reused here since
* no real tasks can be started from a discovery session and
* thus no conflicts are possible.
*/
}
static void
{
if (status != IDM_STATUS_SUCCESS) {
/*
* Could not send the last text response.
* Clear any state and bump the TTT so subsequent
* requests will not match.
*/
}
}
static void
{
/*
* A reject means abandoning this text request.
* Cleanup any state from the request and increment the TTT
* in case the initiator does not get the reject response
* and attempts to resume this request.
*/
}
/*
* Add individual <TargetAddress=ipaddr> tuple to the nvlist
*/
static void
{
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
case AF_INET:
break;
case AF_INET6:
sizeof (ipaddr));
break;
default:
ASSERT(0);
return;
}
}
/*
* Process the special case of the default portal group.
* Network addresses are obtained from the network stack and
* require some reformatting.
*/
static void
{
int pass, i;
struct sockaddr_storage ss;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
/*
* If this request was received on one of the portals,
* output that portal first. Most initiators will try to
* connect on the first portal in the SendTargets response.
* For example, this will avoid the confusing situation of a
* discovery coming in on an IB interface and the initiator
* then doing the normal login on an ethernet interface.
*/
/* Convert the address into sockaddr_storage format */
case sizeof (struct in_addr):
break;
case sizeof (struct in6_addr):
break;
default:
ASSERT(0);
continue;
}
switch (pass) {
case 1:
/*
* On the first pass, skip portals that
* do not match the incoming connection.
*/
continue;
break;
case 2:
/*
* On the second pass, process the
* remaining portals.
*/
continue;
break;
}
/*
* Add portal to the response list.
* By convention, the default portal group tag == 1
*/
}
}
}
/*
* Process a portal group from the configuration database.
*/
static void
{
int pass;
struct sockaddr_storage *ss;
/*
* As with the default portal group, output the portal used by
* the incoming request first.
*/
portal = next_portal) {
switch (pass) {
case 1:
/*
* On the first pass, skip portals that
* do not match the incoming connection.
*/
continue;
break;
case 2:
/*
* On the second pass, process the
* remaining portals.
*/
continue;
break;
}
/* Add portal to the response list */
}
}
}
/*
* Process all the portal groups bound to a particular target.
*/
static void
{
/*
* Look through the portal groups associated with this target.
*/
/* check for the default portal group */
/*
* The default portal group is a special case and will
* return all reasonable interfaces on this node.
*
* A target cannot be bound to other portal groups
* if it is bound to the default portal group.
*/
/* convert the ip address list to nvlist format */
}
return;
}
/*
* Not the default portal group - process the user defined tpgs
*/
/*
* Found a defined portal group - add each portal address.
* As with the default portal group, make 2 passes over
* the addresses in order to output the connection
* address first.
*/
}
}
#ifdef DEBUG
/*
* To test with smaller PDUs in order to force multi-PDU responses,
* set this value such that: 0 < test_max_len < 8192
*/
#endif
/*
* Format a text response PDU from the text buffer and send it.
*/
static void
{
char *base;
#ifdef DEBUG
#endif
do {
} else {
}
/*
* Allocate a PDU and copy in text response buffer
*/
/* Advance the StatSN for each Text Response sent */
/*
* Fill in the response header
*/
if (final) {
ict->ict_text_rsp_len = 0;
ict->ict_text_rsp_valid_len = 0;
ict->ict_text_rsp_off = 0;
} else {
}
/* Send the response on its way */
} while (!final);
/* Free the request pdu */
}
/*
* Clean-up the text buffer if it exists.
*/
void
{
}
ict->ict_text_rsp_len = 0;
ict->ict_text_rsp_valid_len = 0;
ict->ict_text_rsp_off = 0;
}
/*
* Process an iSCSI text command.
*
* This code only handles the common case of a text command
* containing the single tuple SendTargets=All issued during
* a discovery session. The request will always arrive in a
* single PDU, but the response may span multiple PDUs if the
* configuration is large. I.e. many targets and portals.
*
* The request is checked for correctness and then the response
* is generated from the global target into nvlist format. Then
* the nvlist is reformatted into idm textbuf format which reflects
* the iSCSI defined <name=value> specification. Finally, the
* textbuf is sent to the initiator in one or more text response PDUs
*/
void
{
char *kv_pair;
int flags;
char *textbuf;
int textbuflen;
int validlen;
int rc;
/* Cannot handle multi-PDU requests now */
return;
}
/*
* This is the initiator acknowledging our last PDU and
* indicating it is ready for the next PDU in the sequence.
*/
/*
* There can only be one outstanding text request on a
* connection. Make sure this one PDU has the current TTT.
*/
/* XXX combine the following 3 checks after testing */
/* Not part of this sequence */
return;
}
/*
* ITT should match what was saved from first PDU.
*/
/* Not part of this sequence */
return;
}
/*
*/
if (rx_pdu->isp_datalen != 0) {
return;
}
return;
}
/*
* Initiator has started a new text request. Only
* one can be active at a time, so abandon any previous
* text request on this connection.
*/
/* Set the target task tag. */
/* Save the initiator task tag */
/*
* Make sure this is a proper SendTargets request
*/
kv_pair = "SendTargets=All";
/*
* Most common case of SendTargets=All during discovery.
*/
int ipsize;
/* Create an nvlist for response */
return;
}
/* Get the list of local interface addresses */
/* Add targets to the response list */
/* Only report online and onlining targets */
state != TS_STMF_ONLINE)
continue;
/*
* Report target if:
* - it is bound to default TPG
* - one of the addresses of TPGs the target is bound
* to matches incoming connection dst address
*/
if (!(IS_DEFAULT_TPGT(tpgt))) {
&tpgt);
}
continue;
}
}
tgt->target_name) == 0) {
/* Add the portal groups bound to this target */
}
}
if (ipsize > 0)
/* Convert the response nvlist into an idm text buffer */
textbuf = 0;
textbuflen = 0;
validlen = 0;
&textbuflen, &validlen);
if (rc != 0) {
if (textbuf && textbuflen)
return;
}
ict->ict_text_rsp_off = 0;
} else {
/*
* Other cases to handle
* Discovery session:
* SendTargets=<target_name>
* Normal session
* SendTargets=<NULL> - assume target name of session
* All others
* Error
*/
return;
}
}