a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER START
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The contents of this file are subject to the terms of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Common Development and Distribution License (the "License").
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You may not use this file except in compliance with the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or http://www.opensolaris.org/os/licensing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * See the License for the specific language governing permissions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and limitations under the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If applicable, add the following below this CDDL HEADER, with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER END
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/cpuvar.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/types.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/conf.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/file.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sunddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/modctl.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sysmacros.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/socket.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/strsubr.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <inet/tcp.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/nvpair.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/stmf.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/stmf_ioctl.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/portif.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_conn_sm.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_text.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_so.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include "iscsit_isns.h"
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include "iscsit.h"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define IPADDRSTRLEN INET6_ADDRSTRLEN /* space for ipaddr string */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PORTALSTRLEN (IPADDRSTRLEN+16) /* add space for :port,tag */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorevoid
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_text_cmd_fini(iscsit_conn_t *ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The kernel inet_ntop() function formats ipv4 address fields with
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * leading zeros which the win2k initiator interprets as octal.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankovstatic void
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankoviscsit_v4_ntop(struct in_addr *in, char a[], int size)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap unsigned char *p = (unsigned char *) in;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) snprintf(a, size, "%d.%d.%d.%d", *p, *(p+1), *(p+2), *(p+3));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_bump_ttt(iscsit_conn_t *ict)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Set the target task tag. The value will be zero when
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * the connection is created. Increment it and wrap it
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * back to one if we hit the reserved value.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore *
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * The TTT is fabricated since there is no real task associated
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * with a text request. The idm task range is reused here since
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * no real tasks can be started from a discovery session and
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * thus no conflicts are possible.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (++ict->ict_text_rsp_ttt == IDM_TASKIDS_MAX)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_ttt = 1;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_text_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_conn_t *ict = pdu->isp_private;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore idm_pdu_free(pdu);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (status != IDM_STATUS_SUCCESS) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Could not send the last text response.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Clear any state and bump the TTT so subsequent
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * requests will not match.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_cmd_fini(ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_bump_ttt(ict);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_conn_rele(ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_text_reject(idm_pdu_t *req_pdu, uint8_t reason_code)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_conn_t *ict = req_pdu->isp_ic->ic_handle;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * A reject means abandoning this text request.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Cleanup any state from the request and increment the TTT
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * in case the initiator does not get the reject response
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * and attempts to resume this request.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_cmd_fini(ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_bump_ttt(ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_send_reject(ict, req_pdu, reason_code);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(req_pdu, IDM_STATUS_SUCCESS);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Add individual <TargetAddress=ipaddr> tuple to the nvlist
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankoviscsit_add_portal(struct sockaddr_storage *ss, int tag, nvlist_t *nv_resp)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore char ipaddr[IPADDRSTRLEN]; /* ip address string */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore char ta_value[PORTALSTRLEN]; /* target address value */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr_in *sin;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore struct sockaddr_in6 *sin6;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore switch (ss->ss_family) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case AF_INET:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin = (struct sockaddr_in *)ss;
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov iscsit_v4_ntop(&sin->sin_addr, ipaddr, sizeof (ipaddr));
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore (void) snprintf(ta_value, sizeof (ta_value), "%s:%d,%d",
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ipaddr, ntohs(sin->sin_port), tag);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case AF_INET6:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin6 = (struct sockaddr_in6 *)ss;
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov (void) inet_ntop(AF_INET6, &sin6->sin6_addr, ipaddr,
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov sizeof (ipaddr));
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore (void) snprintf(ta_value, sizeof (ta_value), "[%s]:%d,%d",
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ipaddr, ntohs(sin6->sin6_port), tag);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore default:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(0);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore return;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore (void) nvlist_add_string(nv_resp, "TargetAddress", ta_value);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Process the special case of the default portal group.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Network addresses are obtained from the network stack and
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * require some reformatting.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_add_default_portals(iscsit_conn_t *ict, idm_addr_list_t *ipaddr_p,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore nvlist_t *nv_resp)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore int pass, i;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore idm_addr_t *tip;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore struct sockaddr_storage ss;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore struct sockaddr_in *sin;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore struct sockaddr_in6 *sin6;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * If this request was received on one of the portals,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * output that portal first. Most initiators will try to
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * connect on the first portal in the SendTargets response.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * For example, this will avoid the confusing situation of a
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * discovery coming in on an IB interface and the initiator
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * then doing the normal login on an ethernet interface.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin = (struct sockaddr_in *)&ss;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin6 = (struct sockaddr_in6 *)&ss;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore for (pass = 1; pass <= 2; pass++) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore tip = &ipaddr_p->al_addrs[0];
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore for (i = 0; i < ipaddr_p->al_out_cnt; i++, tip++) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Convert the address into sockaddr_storage format */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore switch (tip->a_addr.i_insize) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case sizeof (struct in_addr):
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin->sin_family = AF_INET;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin->sin_port = htons(ISCSI_LISTEN_PORT);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin->sin_addr = tip->a_addr.i_addr.in4;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case sizeof (struct in6_addr):
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin6->sin6_family = AF_INET6;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin6->sin6_port = htons(ISCSI_LISTEN_PORT);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore sin6->sin6_addr = tip->a_addr.i_addr.in6;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore default:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(0);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore switch (pass) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case 1:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * On the first pass, skip portals that
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * do not match the incoming connection.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (idm_ss_compare(&ss, &ict->ict_ic->ic_laddr,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States B_TRUE, B_TRUE) != 0)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case 2:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * On the second pass, process the
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * remaining portals.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (idm_ss_compare(&ss, &ict->ict_ic->ic_laddr,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States B_TRUE, B_TRUE) == 0)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Add portal to the response list.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * By convention, the default portal group tag == 1
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov iscsit_add_portal(&ss, 1, nv_resp);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Process a portal group from the configuration database.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_add_portals(iscsit_conn_t *ict, iscsit_tpgt_t *tpg_list,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore nvlist_t *nv_resp)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore int pass;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_portal_t *portal, *next_portal;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_tpg_t *tpg;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore struct sockaddr_storage *ss;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * As with the default portal group, output the portal used by
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * the incoming request first.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore tpg = tpg_list->tpgt_tpg;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore for (pass = 1; pass <= 2; pass++) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore for (portal = avl_first(&tpg->tpg_portal_list);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore portal != NULL;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore portal = next_portal) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore next_portal = AVL_NEXT(&tpg->tpg_portal_list, portal);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ss = &portal->portal_addr;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore switch (pass) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case 1:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * On the first pass, skip portals that
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * do not match the incoming connection.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (idm_ss_compare(ss, &ict->ict_ic->ic_laddr,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States B_TRUE, B_TRUE) != 0)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore case 2:
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * On the second pass, process the
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * remaining portals.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (idm_ss_compare(ss, &ict->ict_ic->ic_laddr,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States B_TRUE, B_TRUE) == 0)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov /* Add portal to the response list */
59927d313a821b7f3822314ed16fc0a44c128431Yuri Pankov iscsit_add_portal(ss, tpg_list->tpgt_tag, nv_resp);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Process all the portal groups bound to a particular target.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United Statesiscsit_add_tpgs(iscsit_conn_t *ict, iscsit_tgt_t *target,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_addr_list_t *ipaddr_p, nvlist_t *nv_resp)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_tpgt_t *tpg_list;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Look through the portal groups associated with this target.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore mutex_enter(&target->target_mutex);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore tpg_list = avl_first(&target->target_tpgt_list);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* check for the default portal group */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (tpg_list->tpgt_tpg == iscsit_global.global_default_tpg) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * The default portal group is a special case and will
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * return all reasonable interfaces on this node.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore *
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * A target cannot be bound to other portal groups
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * if it is bound to the default portal group.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(AVL_NEXT(&target->target_tpgt_list, tpg_list) == NULL);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (ipaddr_p != NULL) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* convert the ip address list to nvlist format */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_add_default_portals(ict, ipaddr_p, nv_resp);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore mutex_exit(&target->target_mutex);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore return;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Not the default portal group - process the user defined tpgs
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(tpg_list != NULL);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore while (tpg_list != NULL) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(tpg_list->tpgt_tpg != iscsit_global.global_default_tpg);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Found a defined portal group - add each portal address.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * As with the default portal group, make 2 passes over
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * the addresses in order to output the connection
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * address first.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_add_portals(ict, tpg_list, nv_resp);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap tpg_list = AVL_NEXT(&target->target_tpgt_list, tpg_list);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&target->target_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore#ifdef DEBUG
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * To test with smaller PDUs in order to force multi-PDU responses,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * set this value such that: 0 < test_max_len < 8192
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenkouint32_t iscsit_text_max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore#endif
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Format a text response PDU from the text buffer and send it.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorestatic void
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_send_next_text_response(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_text_hdr_t *th_req = (iscsi_text_hdr_t *)rx_pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_text_rsp_hdr_t *th_resp;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore idm_pdu_t *resp;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore uint32_t len, remainder, max_len;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko char *base;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko boolean_t final;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore#ifdef DEBUG
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko if (iscsit_text_max_len > 0 && iscsit_text_max_len < max_len)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore max_len = iscsit_text_max_len;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore#endif
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko do {
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko remainder = ict->ict_text_rsp_valid_len - ict->ict_text_rsp_off;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko if (remainder <= max_len) {
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko len = remainder;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko final = B_TRUE;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko } else {
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko len = max_len;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko final = B_FALSE;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko }
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko /*
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko * Allocate a PDU and copy in text response buffer
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko */
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), len);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko idm_pdu_init(resp, ict->ict_ic, ict,
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko iscsit_text_resp_complete_cb);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko /* Advance the StatSN for each Text Response sent */
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko resp->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko base = ict->ict_text_rsp_buf + ict->ict_text_rsp_off;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko bcopy(base, resp->isp_data, len);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko /*
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko * Fill in the response header
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko */
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp = (iscsi_text_rsp_hdr_t *)resp->isp_hdr;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko bzero(th_resp, sizeof (*th_resp));
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->opcode = ISCSI_OP_TEXT_RSP;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->itt = th_req->itt;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko hton24(th_resp->dlength, len);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko if (final) {
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->flags = ISCSI_FLAG_FINAL;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->ttt = ISCSI_RSVD_TASK_TAG;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko ict->ict_text_rsp_buf = NULL;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko ict->ict_text_rsp_len = 0;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko ict->ict_text_rsp_valid_len = 0;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko ict->ict_text_rsp_off = 0;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko } else {
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->flags = ISCSI_FLAG_TEXT_CONTINUE;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko th_resp->ttt = ict->ict_text_rsp_ttt;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko ict->ict_text_rsp_off += len;
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko }
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko /* Send the response on its way */
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko iscsit_conn_hold(ict);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko iscsit_pdu_tx(resp);
dd647b3d99c9ddb4464975effae545916a9503ffAlexander Stetsenko } while (!final);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Free the request pdu */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Clean-up the text buffer if it exists.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorevoid
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_text_cmd_fini(iscsit_conn_t *ict)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (ict->ict_text_rsp_buf != NULL) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(ict->ict_text_rsp_len != 0);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_buf = NULL;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_len = 0;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_valid_len = 0;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_off = 0;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore}
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore/*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Process an iSCSI text command.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore *
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * This code only handles the common case of a text command
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * containing the single tuple SendTargets=All issued during
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * a discovery session. The request will always arrive in a
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * single PDU, but the response may span multiple PDUs if the
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * configuration is large. I.e. many targets and portals.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore *
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * The request is checked for correctness and then the response
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * is generated from the global target into nvlist format. Then
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * the nvlist is reformatted into idm textbuf format which reflects
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * the iSCSI defined <name=value> specification. Finally, the
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * textbuf is sent to the initiator in one or more text response PDUs
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moorevoid
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Mooreiscsit_pdu_op_text_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore{
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsi_text_hdr_t *th_req = (iscsi_text_hdr_t *)rx_pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvlist_t *nv_resp;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore char *kv_pair;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int flags;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore char *textbuf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int textbuflen;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore int validlen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap flags = th_req->flags;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((flags & ISCSI_FLAG_FINAL) != ISCSI_FLAG_FINAL) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Cannot handle multi-PDU requests now */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu, ISCSI_REJECT_CMD_NOT_SUPPORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (th_req->ttt != ISCSI_RSVD_TASK_TAG) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * This is the initiator acknowledging our last PDU and
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * indicating it is ready for the next PDU in the sequence.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * There can only be one outstanding text request on a
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * connection. Make sure this one PDU has the current TTT.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* XXX combine the following 3 checks after testing */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (th_req->ttt != ict->ict_text_rsp_ttt) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Not part of this sequence */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ISCSI_REJECT_CMD_NOT_SUPPORTED);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore return;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * ITT should match what was saved from first PDU.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (th_req->itt != ict->ict_text_req_itt) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Not part of this sequence */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ISCSI_REJECT_CMD_NOT_SUPPORTED);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore return;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Cannot deal with more key/value pairs now.
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (rx_pdu->isp_datalen != 0) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ISCSI_REJECT_CMD_NOT_SUPPORTED);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore return;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_send_next_text_response(ict, rx_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Initiator has started a new text request. Only
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * one can be active at a time, so abandon any previous
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * text request on this connection.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_cmd_fini(ict);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Set the target task tag. */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_bump_ttt(ict);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /* Save the initiator task tag */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_req_itt = th_req->itt;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore /*
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore * Make sure this is a proper SendTargets request
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap textbuf = (char *)rx_pdu->isp_data;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap textbuflen = rx_pdu->isp_datalen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kv_pair = "SendTargets=All";
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (textbuflen >= strlen(kv_pair) &&
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore strcmp(kv_pair, textbuf) == 0 &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ict->ict_op.op_discovery_session == B_TRUE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Most common case of SendTargets=All during discovery.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov idm_addr_list_t *ipaddr_p;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_tgt_t *tgt, *ntgt;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov int ipsize;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Create an nvlist for response */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (nvlist_alloc(&nv_resp, 0, KM_SLEEP) != 0) {
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSI_REJECT_CMD_NOT_SUPPORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Get the list of local interface addresses */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States ipsize = idm_get_ipaddr(&ipaddr_p);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Add targets to the response list */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSIT_GLOBAL_LOCK(RW_READER);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov for (tgt = avl_first(&iscsit_global.global_target_list);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov tgt != NULL; tgt = ntgt) {
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov struct sockaddr_storage v4sa, *sa;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_tgt_state_t state;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_portal_t *portal;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_tpgt_t *tpgt;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov ntgt = AVL_NEXT(&iscsit_global.global_target_list, tgt);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Only report online and onlining targets */
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov state = tgt->target_state;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore if (state != TS_ONLINING && state != TS_ONLINE &&
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore state != TS_STMF_ONLINE)
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore continue;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /*
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov * Report target if:
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov * - it is bound to default TPG
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov * - one of the addresses of TPGs the target is bound
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov * to matches incoming connection dst address
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov */
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov sa = &ict->ict_ic->ic_laddr;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov mutex_enter(&tgt->target_mutex);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov tpgt = avl_first(&tgt->target_tpgt_list);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov if (!(IS_DEFAULT_TPGT(tpgt))) {
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov portal = iscsit_tgt_lookup_portal(tgt, sa,
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov &tpgt);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov if (portal == NULL &&
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_is_v4_mapped(sa, &v4sa)) {
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov portal = iscsit_tgt_lookup_portal(tgt,
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov &v4sa, &tpgt);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov }
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov if (portal == NULL) {
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov mutex_exit(&tgt->target_mutex);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov continue;
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov }
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_portal_rele(portal);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_tpgt_rele(tpgt);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov }
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov mutex_exit(&tgt->target_mutex);
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov if (nvlist_add_string(nv_resp, "TargetName",
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov tgt->target_name) == 0) {
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Add the portal groups bound to this target */
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov iscsit_add_tpgs(ict, tgt, ipaddr_p, nv_resp);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSIT_GLOBAL_UNLOCK();
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov if (ipsize > 0)
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States kmem_free(ipaddr_p, ipsize);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
483b029ba8436049005eb485fcc9b26f2484f7eaYuri Pankov /* Convert the response nvlist into an idm text buffer */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap textbuf = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap textbuflen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap validlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = idm_nvlist_to_textbuf(nv_resp, &textbuf,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &textbuflen, &validlen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvlist_free(nv_resp);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (textbuf && textbuflen)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(textbuf, textbuflen);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSI_REJECT_CMD_NOT_SUPPORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_buf = textbuf;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_len = textbuflen;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_valid_len = validlen;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ict->ict_text_rsp_off = 0;
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_send_next_text_response(ict, rx_pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Other cases to handle
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Discovery session:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * SendTargets=<target_name>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Normal session
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * SendTargets=<NULL> - assume target name of session
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * All others
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Error
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore iscsit_text_reject(rx_pdu, ISCSI_REJECT_CMD_NOT_SUPPORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}