isns_client.c revision aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <syslog.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <iscsitgt_impl.h>
#include "isns_protocol.h"
#include "isns_client.h"
#include "target.h"
#include "queue.h"
typedef struct {
uint32_t pf_family;
uint32_t ip_len;
uint32_t ai_addrlen;
union {
in_addr_t in;
in6_addr_t in6;
} ip_adr;
} ip_t;
#define ISNS_TGT_LOGOUT 54321
extern target_queue_t *mgmtq;
/*
* Global
* Parameters for ESI/SCN processing.
* scn_port: ESI/SCN port to receive ISNS_ESI & ISNS_SCN messages
* isns_args:
* eid_ip: Entity IP info
*/
static int scn_port = 0;
static esi_scn_arg_t isns_args = {{0}, {0}, 0};
static ip_t eid_ip;
static int num_reg = 0;
static pthread_t scn_tid = 0;
static pthread_t isns_tid = 0;
static Boolean_t isns_shutdown = True;
static Boolean_t connection_thr_bail_out = False;
static int ISNS_SLEEP_SECS = 20;
Boolean_t isns_server_connection_thr_running = False;
target_queue_t *mgmtq = NULL;
static int get_ip_addr(char *node, ip_t *sa);
static int isns_op_all(uint16_t);
static int append_tpgt(tgt_node_t *, isns_pdu_t *);
static void process_esi(int, isns_pdu_t *);
static void process_scn(int, isns_pdu_t *);
static void *esi_scn_thr(void *);
static int process_rsp(isns_pdu_t *, isns_rsp_t *);
static int isns_dev_attr_reg(int, tgt_node_t *, char *, char *);
static int isns_dev_attr_dereg(int, char *);
static int isns_scn_reg(int, char *);
static int isns_scn_dereg(int so, char *node);
static tgt_node_t *find_tgt_by_name(char *, char **);
static tgt_node_t *find_next_tgt(tgt_node_t *, char **);
static int isns_populate_and_update_server_info(Boolean_t state);
static int get_addr_family(char *node);
/*
* find_tgt_by_name searches DB by iscsi name or local name, if found
* returns tgt_node_t. iname needs to be free by caller.
*/
static tgt_node_t *
find_tgt_by_name(char *targ, char **iname)
{
tgt_node_t *tgt = NULL;
while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
tgt)) != NULL) {
if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
== FALSE) {
syslog(LOG_ALERT, "ISNS: Missing iscsi name\n");
break;
}
/* match either iscsi name or local name */
if (strcmp(targ, tgt->x_value) == 0 ||
strcmp(targ, *iname) == 0) {
return (tgt);
}
free(*iname);
}
return (NULL);
}
static tgt_node_t *
find_next_tgt(tgt_node_t *tgt, char **iname)
{
while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
tgt)) != NULL) {
if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
== FALSE) {
continue;
}
return (tgt);
}
return (NULL);
}
/*
* Find ip-addr associated with TPGT, don't send if no ip-addr is
* found for a TPGT
*/
static int
append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd)
{
tgt_node_t *t, *x;
tgt_node_t *pgt = NULL;
tgt_node_t *iplist = NULL;
tgt_node_t *tpgt = NULL;
ip_t eid;
/* Always add the default TPGT (1) */
(void) isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL,
1);
if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
eid_ip.ip_len) != 0) {
return (-1);
}
if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
return (-1);
}
/* Get the remainning TPGT-LIST */
if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL))
!= NULL) {
/* find tgpt from tpgt-list */
while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt))
!= NULL) {
/* update isns only if TPGT contains ip_addr */
while ((tpgt = tgt_node_next_child(main_config,
XML_ELEMENT_TPGT, tpgt)) != NULL) {
if (strcmp(pgt->x_value, tpgt->x_value) != 0)
continue;
if ((iplist = tgt_node_next(tpgt,
XML_ELEMENT_IPADDRLIST, NULL)) != NULL)
break;
}
if (tpgt == NULL || iplist == NULL)
continue;
if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID,
ISNS_PG_TAG_SZ, NULL,
strtol(pgt->x_value, NULL, 0)) != 0) {
return (-1);
}
/* get ip-addr & port */
for (x = iplist->x_child; x; x = x->x_sibling) {
if (get_ip_addr(x->x_value, &eid) < 0)
continue;
if (isns_append_attr(cmd,
ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
eid.ai_addrlen, (void *)&eid.ip_adr,
eid.ip_len) != 0) {
return (-1);
}
if (isns_append_attr(cmd,
ISNS_PG_PORTAL_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
return (-1);
}
}
}
}
return (0);
}
/*
* process_scn()
* -Added/Updated object: nop, initiator is verified during connect
*
* -Removed object: logout_targ if still connected
*
* RFC 4171 section 5.6.5.9
* destination attribute is always the 1st attribute in the SCN message,
* then follows by SCN_BITMAP(35) & Source_Attribute(32)
*/
static void
process_scn(int so, isns_pdu_t *scn)
{
uint8_t *ptr = scn->payload;
isns_tlv_t *tlv;
uint16_t cnt = 0;
uint32_t got_dest = 0;
uint32_t got_source = 0;
uint32_t bitmap = 0;
uint32_t got_bitmap = 0;
char dest[MAXNAMELEN];
char source[MAXNAMELEN];
queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u\n",
scn->payload_len);
if (scn->payload_len < TAG_LEN_SZ) {
syslog(LOG_ALERT, "ISNS SCN message error\n");
return;
}
while (cnt < scn->payload_len) {
/* LINTED */
tlv = (isns_tlv_t *)ptr;
tlv->attr_id = ntohl(tlv->attr_id);
tlv->attr_len = ntohl(tlv->attr_len);
queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u %u\n",
tlv->attr_id, tlv->attr_len);
/*
* devAttrQry the source attribute, process if node_type
* is initiator
*/
switch (tlv->attr_id) {
case ISNS_ISCSI_NAME_ATTR_ID:
if (got_dest == 0) {
bcopy(tlv->attr_value, dest,
tlv->attr_len);
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN dest %s\n", dest);
got_dest = 1;
} else {
bcopy(tlv->attr_value, source,
tlv->attr_len);
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN source %s\n", source);
got_source = 1;
}
break;
case ISNS_ISCSI_SCN_BITMAP_ATTR_ID:
bcopy(tlv->attr_value, &bitmap, tlv->attr_len);
bitmap = ntohl(bitmap);
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN bitmap %u\n", bitmap);
got_bitmap = 1;
break;
default:
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN DEFAULT\n");
break;
}
if (got_source && !got_bitmap) {
queue_prt(mgmtq, Q_ISNS_DBG,
"process_scn: message out-of-order\n");
return;
}
if (got_source && got_bitmap) {
switch (bitmap) {
case ISNS_OBJ_ADDED:
case ISNS_OBJ_UPDATED:
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN OBJ ADDED");
(void) isns_update();
break;
case ISNS_OBJ_REMOVED:
queue_prt(mgmtq, Q_ISNS_DBG,
"PROCESS_SCN OBJ REMOVED");
/* logout target */
if (got_dest == 0) {
syslog(LOG_ALERT,
"ISNS protocol error\n");
continue;
}
logout_targ(dest);
break;
default:
break;
}
/* clear got_xxx */
got_source = 0;
got_bitmap = 1;
}
/* next attribute */
cnt += ISNS_ATTR_SZ(tlv->attr_len);
ptr += ISNS_ATTR_SZ(tlv->attr_len);
}
queue_prt(mgmtq, Q_ISNS_DBG, "DONE PROCESS_SCN\n");
}
/*
* Process ESI requires a success response only
*/
static void
process_esi(int so, isns_pdu_t *esi)
{
isns_rsp_t *cmd;
int pl_len;
if (isns_create_pdu(ISNS_ESI_RSP, 0, (isns_pdu_t **)&cmd) != 0) {
return;
}
pl_len = esi->payload_len + ISNS_STATUS_SZ;
if (pl_len > MAX_PDU_PAYLOAD_SZ) {
syslog(LOG_ALERT, "process_esi: payload size exceeded");
isns_free_pdu(cmd);
return;
}
/* change the xid to the request xid */
cmd->xid = htons(esi->xid);
cmd->status = htonl(ISNS_RSP_SUCCESSFUL);
/* copy original data */
bcopy(esi->payload, cmd->data, esi->payload_len);
cmd->pdu_len = htons(pl_len);
if (isns_send(so, (isns_pdu_t *)cmd) < 0) {
syslog(LOG_ALERT, "process_esi failed to isns_send");
}
isns_free_pdu(cmd);
}
static int
is_isns_server_up(char *server) {
int so;
socklen_t len;
struct sockaddr sa;
/* no server specified */
if (server == NULL) {
return (-1);
}
/*
* open isns server connect and determine which PF_INET to use
*/
if ((so = isns_open(server)) < 0) {
syslog(LOG_ERR,
"isns server %s not found",
server);
return (-1);
}
len = sizeof (sa);
if (getsockname(so, &sa, &len) < 0) {
isns_close(so);
syslog(LOG_ALERT,
"isns getsockname failed");
return (-1);
}
isns_close(so);
if (sa.sa_family != PF_INET &&
sa.sa_family != PF_INET6) {
syslog(LOG_ERR,
"isns unknown domain type");
return (-1);
}
return (0);
}
/*
* This thread sit's in a loop and ensures that it keeps checking for
* connection to isns_server. Once the connection works it registers
* with the isns and bails out.
* We expect the isns server to be fault taulerant and has persistence
* for the registered entries.
*/
static void *
isns_server_connection_thr(void *arg)
{
Boolean_t registered_targets = False;
char server[MAXHOSTNAMELEN + 1] = {0};
while (isns_shutdown == False &&
connection_thr_bail_out == False) {
/* current server */
(void) strcpy(server, isns_args.server);
if (is_isns_server_up(server) == 0) {
if (registered_targets == False) {
/*
* register all targets, what happens if
* no targets are created yet? this should
* not be a failure, when new target gets
* created, update gets call. what if SCN
* register fails?
*/
if (isns_reg_all() == 0) {
/* scn register all targets */
if (isns_op_all(ISNS_SCN_REG) != 0) {
syslog(LOG_ERR,
"SCN registrations"
" failed\n");
(void) isns_op_all(
ISNS_DEV_DEREG);
registered_targets = False;
} else {
registered_targets = True;
break;
}
}
}
} else {
syslog(LOG_INFO,
"isns server %s is not reachable",
server);
registered_targets = False;
}
(void) sleep(ISNS_SLEEP_SECS);
/* If isns was disabled, deregister and close the thread */
if (isns_enabled() == False) {
syslog(LOG_INFO,
"isns server is disabled, dergister target");
isns_fini();
break;
}
}
queue_message_set(mgmtq, 0, msg_pthread_join,
(void *)(uintptr_t)pthread_self());
return (NULL);
}
/*
* esi_scn_thr() is the thread creates an end point to receive and process
* ESI & SCN messages. This thread is created when isns_access is enabled
* and for the duration of the iscsi daemon
*/
static void *
esi_scn_thr(void *arg)
{
struct sockaddr sa, *ai;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
int so, fd, pf;
socklen_t len;
char strport[NI_MAXSERV];
isns_pdu_t *scn = NULL;
struct timeval timeout;
fd_set fdset;
int socket_ready = 0;
pf = get_addr_family(isns_args.entity);
if (pf == PF_INET) {
bzero(&sin, sizeof (sin));
sin.sin_family = PF_INET;
sin.sin_port = htons(0);
sin.sin_addr.s_addr = INADDR_ANY;
ai = (struct sockaddr *)&sin;
len = sizeof (sin);
} else if (pf == PF_INET6) {
bzero(&sin6, sizeof (sin6));
sin6.sin6_family = PF_INET6;
sin6.sin6_port = htons(0);
sin6.sin6_addr = in6addr_any;
ai = (struct sockaddr *)&sin6;
len = sizeof (sin6);
} else {
syslog(LOG_ERR, "Bad address family. Exit esi_scn_thr");
return (NULL);
}
/*
* create and bind SCN socket
* save the scn port info
*/
if ((so = socket(pf, SOCK_STREAM, 0)) == -1) {
syslog(LOG_ALERT, "create isns socket failed");
return (NULL);
}
(void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0);
if (bind(so, ai, len) < 0) {
syslog(LOG_ALERT, "esi_scn_thr: bind failed");
(void) close(so);
return (NULL);
}
/* get scn port info */
len = sizeof (sa);
if (getsockname(so, &sa, &len) < 0) {
syslog(LOG_ALERT, "isns getsockname failed");
(void) close(so);
return (NULL);
}
if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV,
NI_NUMERICSERV) != 0) {
syslog(LOG_ALERT, "isns getnameinfo failed");
(void) close(so);
return (NULL);
}
scn_port = atoi(strport);
if (listen(so, 5) < 0) {
syslog(LOG_ALERT, "esi_scn_thr: failed listen");
(void) close(so);
return (NULL);
}
/* listen for esi or scn messages */
while (isns_shutdown == False) {
/* ISNS_ESI_INTERVAL_ATTR_ID is set to 10s */
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(so, &fdset);
socket_ready = select(so + 1, &fdset, NULL, NULL, &timeout);
/* If disabled bail out, dont care about packets */
if (isns_enabled() == False) {
syslog(LOG_INFO,
"isns server is disabled, dergister target");
isns_fini();
(void) close(so);
return (NULL);
}
if (socket_ready < 0) {
syslog(LOG_ERR,
"esi_scn_thr: select failed, retrying.");
continue;
} else if (socket_ready == 0) { /* timeout */
continue;
} else {
/* Socket is ready */
if ((fd = accept(so, &sa, &len)) < 0) {
syslog(LOG_ALERT, "esi_scn_thr: failed accept");
continue;
}
}
if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) {
/* Just return success for ESI */
switch (scn->func_id) {
case ISNS_ESI:
process_esi(fd, scn);
break;
case ISNS_SCN:
/* call the SCN process function */
process_scn(fd, scn);
break;
default:
syslog(LOG_ERR,
"esi_scn_thr: Invalid funcid %d\n",
scn->func_id);
break;
}
/* free response resource */
isns_free_pdu(scn);
} else {
syslog(LOG_ALERT, "esi_scn_thr fails isns_recv ");
}
(void) close(fd);
}
(void) close(so);
return (NULL);
}
/*
* Perform operation on all targets
*/
static int
isns_op_all(uint16_t op)
{
int so;
tgt_node_t *tgt = NULL;
char *iname;
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_op_all: iSNS discovery is not running."
" Check the previous iSNS initialization error.");
return (-1);
}
if ((so = isns_open(isns_args.server)) == -1) {
syslog(LOG_ERR, "isns_op_all: failed to open isns server %s",
isns_args.server);
return (-1);
}
while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
tgt)) != NULL) {
if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname)
== FALSE) {
continue;
}
switch (op) {
case ISNS_DEV_DEREG:
if (isns_dev_attr_dereg(so, iname) == -1) {
syslog(LOG_ERR,
"ISNS de-register failed\n");
}
num_reg = 0;
break;
case ISNS_SCN_DEREG:
if (isns_scn_dereg(so, iname) == -1) {
syslog(LOG_ERR,
"ISNS SCN de-register failed\n");
}
break;
case ISNS_SCN_REG:
if (isns_scn_reg(so, iname) == -1) {
syslog(LOG_ERR,
"ISNS SCN register failed\n");
}
break;
case ISNS_TGT_LOGOUT:
logout_targ(iname);
break;
default:
break;
}
free(iname);
}
isns_close(so);
return (0);
}
static int
isns_populate_and_update_server_info(Boolean_t update) {
char *isns_srv, *isns_port;
int retcode = 0;
/* get isns server info */
(void) tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
&isns_srv);
if (isns_srv == NULL) {
syslog(LOG_INFO,
"The server has not been setup, "
"but enabling the isns access");
retcode = -1;
return (retcode);
}
isns_port = strchr(isns_srv, ':');
if (isns_port == NULL) {
isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
} else {
isns_args.isns_port = strtoul(isns_port + 1, NULL, 0);
if (isns_args.isns_port == 0) {
isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
}
*isns_port = '\0';
}
if (update == True) {
/* isns_server changed */
if (strcmp(isns_srv, isns_args.server) != 0) {
/* de-reg from old iSNS server if it is setup */
syslog(LOG_INFO,
"Detected a new isns server, deregistering"
" %s", isns_args.server);
(void) isns_dereg_all();
(void) strcpy(isns_args.server, isns_srv);
/* Register with the new server */
if (isns_reg_all() == 0) {
/* scn register all targets */
if (isns_op_all(ISNS_SCN_REG) != 0) {
syslog(LOG_ERR,
"SCN registrations failed\n");
(void) isns_op_all(ISNS_DEV_DEREG);
retcode = -1;
}
}
}
} else {
strcpy(isns_args.server, isns_srv);
}
free(isns_srv);
return (retcode);
}
/*
* isns_init() needs to be call before all ISNS operations.
* Save the isns_server & entity name.
* Start esi_scn_thr to receive ESI & SCN messages
*/
int
isns_init(target_queue_t *q)
{
if (q != NULL)
mgmtq = q;
if (isns_enabled() == False)
return (0);
/* get local hostname for entity usage */
if ((gethostname(isns_args.entity, MAXHOSTNAMELEN) < 0) ||
(get_ip_addr(isns_args.entity, &eid_ip) < 0)) {
syslog(LOG_ERR, "isns_init: failed to get host name or host ip"
" address for ENTITY properties");
return (-1);
}
isns_shutdown = False;
(void) isns_populate_and_update_server_info(False);
if (pthread_create(&scn_tid, NULL,
esi_scn_thr, (void *)&isns_args) !=
0) {
syslog(LOG_ALERT, "isns_init failed to pthread_create");
(void) pthread_kill(isns_tid, SIGKILL);
return (-1);
}
if (pthread_create(&isns_tid, NULL, isns_server_connection_thr,
(void *)NULL) != 0) {
syslog(LOG_ALERT,
"isns_init failed to create the "
"isns connection thr");
return (-1);
}
isns_server_connection_thr_running = True;
return (0);
}
/*
* isns_update gets call on modify_admin, this is changes to
* isns access and/or isns server
*/
int
isns_update()
{
Boolean_t is_isns_enabled = isns_enabled();
/*
* If the isns thread was not started before and we are going
* enabled from disabled start the threads.
*/
if (isns_server_connection_thr_running == False) {
if (is_isns_enabled == True) {
if (isns_init(NULL) != 0) {
return (-1);
} else {
return (0);
}
} else {
syslog(LOG_INFO,
"isns_update: isns is disabled");
}
} else {
/*
* isns is disabled after enabled,
* log off all targets and fini isns service
*/
if (is_isns_enabled == False) {
isns_shutdown = True;
/* pthread_join for the isns thread */
(void) pthread_join(isns_tid, NULL);
(void) pthread_join(scn_tid, NULL);
isns_server_connection_thr_running = False;
} else {
/*
* Incase the original thread is still running
* we should reap it
*/
connection_thr_bail_out = True;
pthread_join(isns_tid, NULL);
connection_thr_bail_out = False;
/*
* Read the configuration file incase the server
* has changed.
*/
if (isns_populate_and_update_server_info(True) == -1) {
return (-1);
}
}
}
return (0);
}
/*
* isns_fini is called when isns access is disabled
*/
void
isns_fini()
{
/*
* de-register all targets 1st, this prevents initiator from
* logging back in
*/
(void) isns_op_all(ISNS_SCN_DEREG);
(void) isns_op_all(ISNS_DEV_DEREG);
/* log off all targets */
(void) isns_op_all(ISNS_TGT_LOGOUT);
}
static int
get_addr_family(char *node) {
struct addrinfo *ai = NULL;
int ret;
if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) {
syslog(LOG_ALERT, "get_addr_family: server %s not found : %s",
node, gai_strerror(ret));
return (-1);
}
ret = ai->ai_family;
freeaddrinfo(ai);
return (ret);
}
static int
get_ip_addr(char *node, ip_t *sa)
{
struct addrinfo *ai = NULL, *aip;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
int ret;
if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) {
syslog(LOG_ALERT, "get_ip_addr: %s not found : %s",
node, gai_strerror(ret));
return (-1);
}
bzero(sa, sizeof (ip_t));
aip = ai;
do {
sa->ai_addrlen = aip->ai_addrlen;
sa->pf_family = aip->ai_family;
switch (aip->ai_family) {
case PF_INET:
/* LINTED */
sin = (struct sockaddr_in *)aip->ai_addr;
sa->ip_len = sizeof (in_addr_t);
bcopy(&sin->sin_addr, (void *)&sa->ip_adr.in,
sa->ip_len);
freeaddrinfo(ai);
return (0);
case PF_INET6:
/* LINTED */
sin6 = (struct sockaddr_in6 *)aip->ai_addr;
sa->ip_len = sizeof (in6_addr_t);
bcopy(&sin6->sin6_addr, &sa->ip_adr.in6,
sa->ip_len);
freeaddrinfo(ai);
return (0);
default:
continue;
}
} while ((aip = aip->ai_next) != NULL);
freeaddrinfo(ai);
return (-1);
}
/*
* Process isns response, need to verify same transaction id, func_id
* as the isns command, the isns command is in network byte order,
* the isns response is in host byte order
*/
static int
process_rsp(isns_pdu_t *cmd, isns_rsp_t *rsp)
{
queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_RSP");
/*
* Process responses:
* -verify sucessful response
* -verify match xid
* -process operating attributes
* For DevAttrReg & DevAttrQry and most isns command,
* the response func_id is command_func_id | 0x8000.
*/
rsp->status = ntohl(rsp->status);
if (rsp->status != ISNS_RSP_SUCCESSFUL ||
rsp->xid != ntohs(cmd->xid) ||
rsp->func_id != (ntohs(cmd->func_id) | 0x8000)) {
queue_prt(mgmtq, Q_ISNS_DBG,
"cmd failed with: status= %d xid= %d %d "\
"response attribute %x\n", rsp->status, rsp->xid,\
ntohs(cmd->xid), rsp->func_id);
return (-1);
}
return (0);
}
/*
* DevAttrDereg
*/
static int
isns_dev_attr_dereg(int so, char *node)
{
isns_pdu_t *cmd = NULL;
isns_rsp_t *rsp = NULL;
uint32_t flags = 0;
int ret = -1;
queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_DEREG");
if (isns_create_pdu(ISNS_DEV_DEREG, flags, &cmd) != 0) {
return (-1);
}
/* add source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
/* add delimiter */
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
goto error;
}
/* add operation attributes */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
/* send pdu */
if (isns_send(so, cmd) == -1) {
syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_send");
goto error;
}
/* get isns response */
if (isns_recv(so, &rsp) == -1) {
syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_recv ");
goto error;
}
/* process response */
if (process_rsp(cmd, rsp) == 0) {
/*
* Keep the num_reg to a non-negative number.
* num_reg is used to keep track of whether there was
* any registration occurred or not. Deregstration should
* be followed by registration but in case dereg occurs
* and somehow it is succeeded keeping num_reg to 0 prevent
* any negative effect on subsequent registration.
*/
if (num_reg > 0) num_reg--;
ret = 0;
}
error:
/* Free all resouces here */
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
return (ret);
}
/*
* Register a new node, need to find another node that is already registered
* DevAttrReg
* RFC 4171 Section 5.6.5.5 indicated SCN-port-tag (23) needed to be
* included in the registration
* Also need to register ESI-port-tag (20) see Section 6.3.5
*/
static int
isns_dev_attr_reg(int so, tgt_node_t *tgt, char *node, char *alias)
{
isns_pdu_t *cmd = NULL;
isns_rsp_t *rsp = NULL;
uint32_t flags = 0;
int ret = 0;
Boolean_t found = False;
tgt_node_t *src = NULL;
char *src_nm = NULL;
queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_REG");
if ((so = isns_open(isns_args.server)) == -1) {
return (-1);
}
if (num_reg == 0) {
flags |= ISNS_FLAG_REPLACE_REG;
}
if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) {
return (-1);
}
if (num_reg == 0) {
/* add new node to source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
} else {
/* find a registered node to use */
do {
src = find_next_tgt(src, &src_nm);
if (src == NULL) {
syslog(LOG_ALERT, "ISNS out of sync\n");
goto error;
}
if (tgt == src) {
free(src_nm);
src_nm = NULL;
continue;
} else {
found = True;
}
} while (found == False);
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(src_nm), src_nm, 0) != 0) {
goto error;
}
}
/* add message key attribute */
if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
goto error;
}
/* add delimiter */
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
goto error;
}
/* add operation attributes */
/* entity id */
if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
goto error;
}
/* entity type */
if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID,
ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
goto error;
}
/*
* Register entity portal properties the 1st time
*/
if (num_reg == 0) {
/* portal ip-addr */
if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID,
eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
eid_ip.ip_len) != 0) {
goto error;
}
/* portal port */
if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
goto error;
}
/* ESI interval */
if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID,
ISNS_ESI_TICK_SZ, NULL, 10) != 0) {
goto error;
}
/* scn port */
if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, scn_port) != 0) {
goto error;
}
/* esi port */
if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, scn_port) != 0) {
goto error;
}
}
/* iscsi node name */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
/* iscsi node type */
if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE) != 0) {
goto error;
}
/* iscsi node alias */
if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
STRLEN(alias), alias, 0) != 0) {
goto error;
}
/* PGT */
if (append_tpgt(tgt, cmd) != 0) {
goto error;
}
/* send pdu */
if (isns_send(so, cmd) == -1) {
goto error;
}
/* get isns response */
if (isns_recv(so, &rsp) == -1) {
goto error;
}
/* process response */
if ((ret = process_rsp(cmd, rsp)) == 0) {
num_reg++;
}
error:
/* Free all resouces here */
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
if (src_nm)
free(src_nm);
return (ret);
}
/*
* DevAttrQry for iscsi initiator
* See RFC 4171 Sect. 5.6.5.2 for query detail
*/
static int
isns_dev_attr_qry(int so, char *target, char *initiator)
{
isns_pdu_t *cmd;
isns_rsp_t *rsp;
uint32_t flags = 0;
int ret = -1;
size_t remain;
isns_tlv_t *tlv;
uint8_t *ptr;
queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_QRY");
if (isns_create_pdu(ISNS_DEV_ATTR_QRY, flags, &cmd) != 0) {
return (-1);
}
/* source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(target), target, 0) == -1) {
goto error;
}
/* message key attribute */
/* iscsi initiator node type */
if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
ISNS_NODE_TYP_SZ, NULL, ISNS_INITIATOR_NODE_TYPE) == -1) {
goto error;
}
/* delimiter */
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
goto error;
}
/*
* operating attributes
* Query Iscsi initiator with zero length TLV operating
* attribute
*/
/* iscsi name */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
0, NULL, 0) != 0) {
goto error;
}
if (isns_send(so, cmd) == -1) {
syslog(LOG_ERR, "isns_dev_attr_qry fails isns_send");
goto error;
}
/* recv response */
if (isns_recv(so, &rsp) == -1) {
syslog(LOG_ERR, "isns_dev_attr_qry fails isns_recv ");
goto error;
}
/* process response */
if ((ret = process_rsp(cmd, rsp)) == 0) {
/* compare initiator name to the response, success if found */
/* subtract out status word */
remain = rsp->pdu_len - ISNS_STATUS_SZ;
ptr = rsp->data;
while (remain > 0) {
/* LINTED */
tlv = (isns_tlv_t *)ptr;
/* debug only */
print_ntoh_tlv(tlv);
/* process tag-len-value */
ntoh_tlv(tlv);
/*
* let's process the data, only interested
* in iscsi name, skip everything else for
* now.
*/
if (tlv->attr_id == ISNS_ISCSI_NAME_ATTR_ID) {
if (strncmp((char *)tlv->attr_value, initiator,
tlv->attr_len) == 0) {
break;
}
}
/* next tlv */
remain -= ISNS_ATTR_SZ(tlv->attr_len);
ptr += ISNS_ATTR_SZ(tlv->attr_len);
}
ret = (remain > 0) ? 1 : 0;
}
error:
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
return (ret);
}
/*
* SCNReg
* See RFC 4171 Section 5.6.5.5
*/
static int
isns_scn_reg(int so, char *node)
{
isns_pdu_t *cmd;
isns_rsp_t *rsp;
uint32_t flags = 0;
uint32_t bitmap = 0;
int ret = -1;
queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_REG");
if (isns_create_pdu(ISNS_SCN_REG, flags, &cmd) != 0) {
return (-1);
}
/* source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) == -1) {
goto error;
}
/* message key attribute */
/* iscsi initiator node name */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
/* delimiter */
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
goto error;
}
/* SCN bitmap */
bitmap = ISNS_INIT_SELF_INFO_ONLY | ISNS_OBJ_REMOVED |
ISNS_OBJ_ADDED | ISNS_OBJ_UPDATED;
if (isns_append_attr(cmd, ISNS_ISCSI_SCN_BITMAP_ATTR_ID,
ISNS_SCN_BITMAP_SZ, NULL, bitmap) == -1) {
goto error;
}
if (isns_send(so, cmd) == -1) {
syslog(LOG_ERR, "isns_scn_reg fails isns_send");
goto error;
}
if (isns_recv(so, &rsp) == -1) {
syslog(LOG_ERR, "isns_scn_reg fails isns_recv ");
goto error;
}
/* process response */
if (process_rsp(cmd, rsp) == 0) {
ret = 0;
}
error:
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
return (ret);
}
/*
* SCNDereg
*/
static int
isns_scn_dereg(int so, char *node)
{
isns_pdu_t *cmd = NULL;
isns_rsp_t *rsp = NULL;
uint32_t flags = 0;
int ret = -1;
queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_DEREG");
if (isns_create_pdu(ISNS_SCN_DEREG, flags, &cmd) != 0) {
return (-1);
}
/* source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) == -1) {
goto error;
}
/* message key attribute */
/* iscsi initiator node name */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(node), node, 0) != 0) {
goto error;
}
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) {
goto error;
}
if (isns_send(so, cmd) == -1) {
syslog(LOG_ERR, "isns_scn_reg fails isns_send");
goto error;
}
if (isns_recv(so, &rsp) == -1) {
syslog(LOG_ERR, "isns_scn_reg fails isns_recv ");
goto error;
}
/* process response */
if (process_rsp(cmd, rsp) == 0) {
ret = 0;
}
error:
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
return (ret);
}
/*
* isns_reg is called to register new target
*/
int
isns_reg(char *targ)
{
int so;
tgt_node_t *tgt;
char *iqn = NULL;
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_reg: iSNS discovery is not running."
" Check the previous iSNS initialization error.");
return (-1);
}
if ((so = isns_open(isns_args.server)) == -1) {
syslog(LOG_ERR, "isns_reg failed with server: %s",
isns_args.server);
return (-1);
}
/*
* Open targets_config and devAttrReg all nodes
*/
if ((tgt = find_tgt_by_name(targ, &iqn)) != NULL) {
if (isns_dev_attr_reg(so, tgt, iqn, tgt->x_value) != 0) {
syslog(LOG_ALERT, "ISNS registration failed %s\n",
tgt->x_value);
goto error;
}
if (isns_scn_reg(so, iqn) == -1) {
syslog(LOG_ERR, "ISNS SCN register failed\n");
}
}
error:
if (iqn)
free(iqn);
isns_close(so);
return (0);
}
/*
* Register all iscsi target nodes from the XML database
* Alway use the ISNS_FLAG_REPLACE_REG flag
*/
int
isns_reg_all()
{
int so;
uint32_t flags = ISNS_FLAG_REPLACE_REG;
isns_pdu_t *cmd = NULL;
isns_rsp_t *rsp = NULL;
char *n = NULL;
char *a = NULL;
char alias[MAXNAMELEN];
char iname[MAXNAMELEN];
tgt_node_t *tgt = NULL;
int ret = -1;
int tgt_cnt = 0;
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_reg_all: iSNS discovery is not running."
" Check the previous iSNS initialization error.");
return (-1);
}
/*
* get the 1st target and use it for the source attribute
*/
if ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, tgt))
== NULL) {
return (0);
}
if (tgt->x_value == NULL) {
syslog(LOG_ALERT, "ISNS: target with NULL local name\n");
return (-1);
}
if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
== FALSE) {
syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n");
return (-1);
}
(void) strcpy(iname, n);
free(n);
if ((so = isns_open(isns_args.server)) == -1) {
syslog(LOG_ALERT, "ISNS: fails to connect to %s\n",
isns_args.server);
return (-1);
}
if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) {
goto error;
}
/* source attribute */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(iname), iname, 0) != 0) {
goto error;
}
/* add message key attribute */
if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
goto error;
}
/* add delimiter */
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
goto error;
}
/* entity id */
if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
goto error;
}
/* entity type */
if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID,
ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
goto error;
}
/* portal ip-addr */
if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID,
eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
eid_ip.ip_len) != 0) {
goto error;
}
/* portal port */
if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
goto error;
}
/* ESI interval */
if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID,
ISNS_ESI_TICK_SZ, NULL, 10) != 0) {
goto error;
}
/* scn port */
if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, scn_port) != 0) {
goto error;
}
/* esi port */
if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID,
ISNS_PORT_SZ, NULL, scn_port) != 0) {
goto error;
}
/*
* Open targets_config and devAttrReg all nodes
*/
tgt = NULL;
while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
tgt)) != NULL) {
if (tgt->x_value == NULL) {
syslog(LOG_ALERT, "ISNS: target with NULL name\n");
continue;
}
/* use this value as alias if alias is not set */
(void) strcpy(alias, tgt->x_value);
if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
== FALSE) {
continue;
}
(void) strcpy(iname, n);
free(n);
/* find alias */
if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a)
== TRUE) {
(void) strcpy(alias, a);
free(a);
}
tgt_cnt++; /* increment target count */
/* operation attributes */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(iname), iname, 0) != 0) {
goto error;
}
if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
4, NULL, ISNS_TARGET_NODE_TYPE) != 0) {
goto error;
}
if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
STRLEN(alias), alias, 0) != 0) {
goto error;
}
if (append_tpgt(tgt, cmd) != 0) {
goto error;
}
}
/* send pdu */
if (isns_send(so, cmd) == -1) {
goto error;
}
/* get isns response */
if (isns_recv(so, &rsp) == -1) {
goto error;
}
/* process response */
if (process_rsp(cmd, rsp) == 0) {
ret = 0;
num_reg = tgt_cnt;
queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful");
} else {
syslog(LOG_ALERT, "DevAttrReg failed");
}
error:
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
isns_close(so);
return (ret);
}
/*
* Deregister an iscsi target node
*/
int
isns_dereg(char *name)
{
int so;
int ret;
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_dereg: iSNS discovery is not running."
" Check the previous iSNS initialization error.");
return (-1);
}
if ((so = isns_open(isns_args.server)) == -1) {
return (-1);
}
ret = isns_dev_attr_dereg(so, name);
isns_close(so);
return (ret);
}
/*
* Update an existing iscsi target property
*/
int
isns_dev_update(char *targ, uint32_t mods)
{
int so;
int flags = 0; /* update only */
char *iname = NULL;
char *dummy = NULL;
char alias[MAXNAMELEN];
tgt_node_t *tgt = NULL;
isns_pdu_t *cmd;
isns_rsp_t *rsp;
int ret = -1;
if (mods == 0)
return (0);
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_dev_update: iSNS discovery is not running."
" Check the previous iSNS initialization error.");
return (-1);
}
if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) {
if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) ==
True) {
(void) strcpy(alias, dummy);
free(dummy);
} else
(void) strcpy(alias, tgt->x_value);
if ((so = isns_open(isns_args.server)) < 0) {
goto error;
}
if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) {
goto error;
}
/* source attr, msg key, delimiter */
if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(iname), iname, 0) != 0) {
goto error;
}
if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
goto error;
}
if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)
!= 0) {
goto error;
}
/*
* get current operating attributes, alias & portal group
* objects, these should be the only things that get change
*/
(void) isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
STRLEN(iname), iname, 0);
(void) isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE);
if (mods & ISNS_MOD_ALIAS)
if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
STRLEN(alias), alias, 0) != 0) {
goto error;
}
if (mods & ISNS_MOD_TPGT)
if (append_tpgt(tgt, cmd) != 0) {
goto error;
}
if (isns_send(so, (isns_pdu_t *)cmd) < 0) {
goto error;
}
if (isns_recv(so, &rsp) == -1) {
goto error;
}
/* process response, if failed do a isns_reg_all */
if ((ret = process_rsp(cmd, rsp)) == -1) {
if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) {
syslog(LOG_ALERT, "ISNS register failed\n");
goto error;
}
ret = 0;
} else {
if (isns_scn_reg(so, iname) == -1) {
syslog(LOG_ERR, "ISNS SCN register failed\n");
goto error;
}
ret = 0;
}
} else {
syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias);
}
error:
if (cmd)
isns_free_pdu(cmd);
if (rsp)
isns_free_pdu(rsp);
if (iname)
free(iname);
isns_close(so);
return (ret);
}
/*
* Deregister all iscsi target nodes from the XML database
*/
int
isns_dereg_all()
{
return (isns_op_all(ISNS_DEV_DEREG));
}
int
isns_scn_reg_all()
{
return (isns_op_all(ISNS_SCN_REG));
}
int
isns_scn_dereg_all()
{
return (isns_op_all(ISNS_SCN_DEREG));
}
/*
* Query an iscsi initiator node
*/
Boolean_t
isns_qry_initiator(char *target, char *initiator)
{
int so;
int ret;
if (isns_server_connection_thr_running == False) {
syslog(LOG_ERR,
"isns_qry_initiator: iSNS discovery is not running"
" Check the previous iSNS initialization error.");
return (-1);
}
if ((so = isns_open(isns_args.server)) == -1) {
syslog(LOG_ERR, "isns_qry failed");
return (-1);
}
ret = isns_dev_attr_qry(so, target, initiator);
isns_close(so);
return (ret == 1 ? True : False);
}
Boolean_t
isns_enabled()
{
Boolean_t isns_access = False;
char *isns_srv = NULL;
(void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS,
&isns_access);
/* get isns server info */
if (isns_access == True) {
if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
&isns_srv) == True) {
free(isns_srv);
return (True);
}
}
return (False);
}