Home | History | Annotate | Line # | Download | only in iscsid
iscsid_discover.c revision 1.3.2.1
      1  1.3.2.1       jdc /*	$NetBSD: iscsid_discover.c,v 1.3.2.1 2012/07/03 20:48:40 jdc Exp $	*/
      2      1.1       agc 
      3      1.1       agc /*-
      4      1.1       agc  * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
      5      1.1       agc  * All rights reserved.
      6      1.1       agc  *
      7      1.1       agc  * This code is derived from software contributed to The NetBSD Foundation
      8      1.1       agc  * by Wasabi Systems, Inc.
      9      1.1       agc  *
     10      1.1       agc  * Redistribution and use in source and binary forms, with or without
     11      1.1       agc  * modification, are permitted provided that the following conditions
     12      1.1       agc  * are met:
     13      1.1       agc  * 1. Redistributions of source code must retain the above copyright
     14      1.1       agc  *    notice, this list of conditions and the following disclaimer.
     15      1.1       agc  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1       agc  *    notice, this list of conditions and the following disclaimer in the
     17      1.1       agc  *    documentation and/or other materials provided with the distribution.
     18      1.1       agc  *
     19      1.1       agc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20      1.1       agc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21      1.1       agc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22      1.1       agc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23      1.1       agc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24      1.1       agc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25      1.1       agc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26      1.1       agc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27      1.1       agc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28      1.1       agc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29      1.1       agc  * POSSIBILITY OF SUCH DAMAGE.
     30      1.1       agc  */
     31      1.1       agc 
     32      1.1       agc #ifndef ISCSI_MINIMAL
     33      1.1       agc 
     34      1.1       agc #include "iscsid_globals.h"
     35      1.1       agc #include "isns.h"
     36      1.1       agc #include "isns_defs.h"
     37      1.1       agc 
     38      1.1       agc #include <sys/socket.h>
     39      1.1       agc #include <netinet/in.h>
     40      1.1       agc #include <netinet/tcp.h>
     41      1.1       agc #include <netdb.h>
     42      1.1       agc 
     43      1.1       agc #define MY_FLAGS  ISNS_FLAG_REPLACE_REG
     44      1.1       agc 
     45      1.1       agc 
     46      1.1       agc /**********************************************************************
     47      1.1       agc **********************************************************************/
     48      1.1       agc 
     49      1.1       agc uint32_t isns_id = 0;			/* isns ID counter */
     50      1.1       agc 
     51      1.1       agc ISNS_HANDLE isns_handle = ISNS_INVALID_HANDLE;
     52      1.1       agc 
     53      1.1       agc /**********************************************************************
     54      1.1       agc **********************************************************************/
     55      1.1       agc 
     56      1.1       agc /*
     57      1.1       agc  * xlate_ip
     58      1.1       agc  *  Support routine to translate binary IP into string form for storage in
     59      1.1       agc  *  target object. Handles IPv6 and IPv4 formats.
     60      1.1       agc  *
     61      1.1       agc  * Parameters:
     62      1.1       agc  *       dest  the destination string
     63      1.1       agc  *       data  the source (from iSNS address field)
     64      1.1       agc  *
     65      1.1       agc  * Returns:     status
     66      1.1       agc  */
     67      1.1       agc 
     68      1.3       agc static void
     69      1.2  christos xlate_ip(uint8_t *dest, size_t size, void *data)
     70      1.1       agc {
     71      1.1       agc 	uint16_t *wdt = (uint16_t *) data;
     72      1.1       agc 	size_t	cc;
     73      1.1       agc 	int i;
     74      1.2  christos 	char *dst = (char *)dest;
     75      1.2  christos 	char *dt = data;
     76      1.1       agc 
     77      1.1       agc 	for (i = 0; i < 5 && !wdt[i]; i++) {
     78      1.1       agc 	}
     79      1.1       agc 	if (i == 5 && wdt[5] == 0xffff) {
     80      1.2  christos 		snprintf(dst, size, "%d.%d.%d.%d",
     81      1.2  christos 			dt[12], dt[13], dt[14], dt[15]);
     82      1.1       agc 	} else {
     83      1.1       agc 		for (cc = 0, i = 0; i < 7; i++) {
     84      1.2  christos 			cc += snprintf(&dst[cc], size - cc, "%x:", wdt[i]);
     85      1.1       agc 		}
     86      1.2  christos 		snprintf(&dst[cc], size - cc, "%x", wdt[7]);
     87      1.1       agc 	}
     88      1.1       agc }
     89      1.1       agc 
     90      1.1       agc 
     91      1.1       agc /*
     92      1.1       agc  * get_isns_target_info
     93      1.1       agc  *  Support routine to query the server for the attributes of the given target.
     94      1.1       agc  *
     95      1.1       agc  * Parameters:
     96      1.1       agc  *       TargetName  The target name to query.
     97      1.1       agc  *
     98      1.1       agc  * Returns:     status
     99      1.1       agc  */
    100      1.1       agc 
    101      1.3       agc static uint32_t
    102      1.1       agc get_isns_target_info(isns_t * isns, uint8_t * TargetName)
    103      1.1       agc {
    104      1.1       agc 	int retval;
    105      1.1       agc 	ISNS_TRANS t;
    106      1.1       agc 	uint32_t tag;
    107      1.2  christos 	uint32_t data_len;
    108      1.1       agc 	void *data_p;
    109      1.1       agc 	uint32_t u32;
    110      1.1       agc 	struct timespec tout = { 5, 0 };
    111      1.1       agc 	uint32_t status;
    112      1.1       agc 	target_t *targ;
    113      1.1       agc 	char name[ISCSI_STRING_LENGTH];
    114      1.1       agc 	char alias[ISCSI_STRING_LENGTH];
    115      1.1       agc 	iscsi_portal_address_t addr;
    116      1.1       agc 
    117      1.2  christos 	t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS);
    118      1.2  christos 	if (ISNS_INVALID_TRANS == t) {
    119      1.2  christos 		DEBOUT(("%s: get_targets iscsi_new_trans failed\n", __func__));
    120      1.1       agc 		return ISCSID_STATUS_NO_RESOURCES;
    121      1.1       agc 	}
    122      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
    123      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
    124      1.1       agc 
    125      1.1       agc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
    126      1.1       agc 
    127      1.1       agc 	isns_add_tlv(t, isnst_iSCSIName, 0, NULL);	/* 32: name */
    128      1.1       agc 	isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL);	/* 33: node type */
    129      1.1       agc 	isns_add_tlv(t, isnst_iSCSIAlias, 0, NULL);	/* 34: alias */
    130      1.1       agc 	/* ToDo: get security attributes... */
    131      1.1       agc 	/* isns_add_tlv (t, isnst_PortalSecBmap, 0, NULL); */
    132      1.1       agc 	/*tag=27: security bitmap */
    133      1.1       agc 
    134      1.1       agc 	retval = isns_send_trans(t, &tout, &status);
    135      1.1       agc 	DEB(9, ("isns_send_trans called, returns %d, status %d\n", retval, status));
    136      1.1       agc 	if (retval) {
    137      1.1       agc 		DEBOUT(("iSNS Attribute Query failed, rc = %d\n", retval));
    138      1.1       agc 		isns_free_trans(t);
    139      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    140      1.1       agc 	}
    141      1.1       agc 	/* First is target name (the one we put in), ignore */
    142      1.1       agc 	if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
    143      1.1       agc 		DEBOUT(("iSNS Attribute Query returned nothing\n"));
    144      1.1       agc 		isns_free_trans(t);
    145      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    146      1.1       agc 	}
    147      1.1       agc 	if (tag != isnst_iSCSIName) {
    148      1.1       agc 		DEBOUT(("iSNS Query returned bad type (tag = %d, length = %d)\n",
    149      1.1       agc 				tag, data_len));
    150      1.1       agc 		isns_free_trans(t);
    151      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    152      1.1       agc 	}
    153      1.1       agc 
    154      1.1       agc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    155      1.1       agc 	if (tag != isnst_Delimiter) {
    156      1.1       agc 		DEBOUT(("Attr Query Missing Delimiter (tag = %d, length = %d)\n",
    157      1.1       agc 				tag, data_len));
    158      1.1       agc 		isns_free_trans(t);
    159      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    160      1.1       agc 	}
    161      1.1       agc 
    162      1.1       agc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    163      1.1       agc 	if (tag != isnst_iSCSIName || !data_len || data_len >= ISCSI_STRING_LENGTH) {
    164      1.1       agc 		DEBOUT(("iSNS Query returned no or invalid name (tag = %d, "
    165      1.1       agc 				"length = %d)\n", tag, data_len));
    166      1.1       agc 		isns_free_trans(t);
    167      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    168      1.1       agc 	}
    169      1.1       agc 	strlcpy(name, (char *) data_p, sizeof(name));
    170      1.1       agc 
    171      1.1       agc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    172      1.1       agc 	if (tag != isnst_iSCSINodeType || data_len != 4) {
    173      1.1       agc 		DEBOUT(("iSNS Query returned no or invalid node type (tag = %d, "
    174      1.1       agc 				"length = %d)\n", tag, data_len));
    175      1.1       agc 		isns_free_trans(t);
    176      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    177      1.1       agc 	}
    178      1.1       agc 	u32 = ntohl(*((uint32_t *) data_p));
    179      1.1       agc 	if (!(u32 & 1)) {
    180      1.1       agc 		DEBOUT(("iSNS Query returned bad type (type=%x, should be 1)\n", u32));
    181      1.1       agc 		isns_free_trans(t);
    182      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    183      1.1       agc 	}
    184      1.1       agc 
    185      1.1       agc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    186      1.1       agc 	if (tag == isnst_iSCSIAlias) {
    187      1.1       agc 		if (data_len >= ISCSI_STRING_LENGTH) {
    188      1.1       agc 			DEBOUT(("iSNS Query returned invalid alias (tag=%d, length=%d)\n",
    189      1.1       agc 					tag, data_len));
    190      1.1       agc 			isns_free_trans(t);
    191      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    192      1.1       agc 		}
    193      1.1       agc 		strlcpy(alias, (char *) data_p, sizeof(alias));
    194      1.1       agc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    195      1.1       agc 	} else
    196      1.1       agc 		alias[0] = 0;
    197      1.1       agc 
    198      1.1       agc 	isns_free_trans(t);
    199      1.1       agc 
    200      1.1       agc 	if (ISNS_INVALID_TRANS ==
    201      1.1       agc 		(t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS))) {
    202      1.1       agc 		DEBOUT(("get_targets iscsi_new_trans failed\n"));
    203      1.1       agc 		return ISCSID_STATUS_NO_RESOURCES;
    204      1.1       agc 	}
    205      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
    206      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
    207      1.1       agc 
    208      1.1       agc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
    209      1.1       agc 
    210      1.1       agc 	isns_add_tlv(t, isnst_PGiSCSIName, 0, NULL);	/* 48: portal name */
    211      1.1       agc 	isns_add_tlv(t, isnst_PGPortIPAddr, 0, NULL);	/* 49: portal IP */
    212      1.1       agc 	isns_add_tlv(t, isnst_PGPortIPPort, 0, NULL);	/* 50: portal port */
    213      1.1       agc 	isns_add_tlv(t, isnst_PGTag, 0, NULL);	/* 51: group tag */
    214      1.1       agc 
    215      1.1       agc 	retval = isns_send_trans(t, &tout, &status);
    216      1.1       agc 	DEB(9, ("isns_send_trans called, returns %d, status %d\n", retval, status));
    217      1.1       agc 	if (retval) {
    218      1.1       agc 		DEBOUT(("iSNS Attribute Query failed, rc = %d\n", retval));
    219      1.1       agc 		isns_free_trans(t);
    220      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    221      1.1       agc 	}
    222      1.1       agc 	/* First is target name (the one we put in), ignore */
    223      1.1       agc 	if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
    224      1.1       agc 		DEBOUT(("iSNS Attribute Query returned nothing\n"));
    225      1.1       agc 		isns_free_trans(t);
    226      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    227      1.1       agc 	}
    228      1.1       agc 	if (tag != isnst_iSCSIName) {
    229      1.1       agc 		DEBOUT(("iSNS Query2 returned bad name (tag = %d, length = %d)\n",
    230      1.1       agc 				tag, data_len));
    231      1.1       agc 		isns_free_trans(t);
    232      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    233      1.1       agc 	}
    234      1.1       agc 
    235      1.1       agc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    236      1.1       agc 	if (tag != isnst_Delimiter) {
    237      1.1       agc 		DEBOUT(("Attr Query2 Missing Delimiter (tag = %d, length = %d)\n",
    238      1.1       agc 				tag, data_len));
    239      1.1       agc 		isns_free_trans(t);
    240      1.1       agc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
    241      1.1       agc 	}
    242      1.1       agc 
    243      1.1       agc 	while (!isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
    244      1.1       agc 		if (tag != isnst_PGiSCSIName || !data_len ||
    245      1.1       agc 			data_len >= ISCSI_STRING_LENGTH) {
    246      1.1       agc 			DEBOUT(("iSNS Query2 returned no or invalid name (tag=%d, "
    247      1.1       agc 					"length=%d)\n", tag, data_len));
    248      1.1       agc 			isns_free_trans(t);
    249      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    250      1.1       agc 		}
    251      1.1       agc 		strlcpy(name, (char *) data_p, sizeof(name));
    252      1.1       agc 
    253      1.1       agc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    254      1.1       agc 		if (tag != isnst_PGPortIPAddr || data_len != 16) {
    255      1.1       agc 			DEBOUT(("iSNS Query returned no or invalid address (tag=%d, "
    256      1.1       agc 					"length=%d)\n", tag, data_len));
    257      1.1       agc 			isns_free_trans(t);
    258      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    259      1.1       agc 		}
    260      1.1       agc 		xlate_ip(addr.address, sizeof(addr.address), (uint8_t *) data_p);
    261      1.1       agc 
    262      1.1       agc 		/* Now comes the port */
    263      1.1       agc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    264      1.1       agc 		if (tag != isnst_PGPortIPPort || data_len != 4) {
    265      1.1       agc 			DEBOUT(("iSNS Query returned no or invalid port (tag=%d, "
    266      1.1       agc 					"length=%d)\n", tag, data_len));
    267      1.1       agc 			isns_free_trans(t);
    268      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    269      1.1       agc 		}
    270      1.1       agc 		u32 = ntohl(*((uint32_t *) data_p));
    271      1.1       agc 		if (u32 & 0xffff0000) {
    272      1.1       agc 			DEBOUT(("iSNS Query returned invalid port (flags=%x, "
    273      1.1       agc 					"should be 0)\n", u32 >> 16));
    274      1.1       agc 			isns_free_trans(t);
    275      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    276      1.1       agc 		}
    277      1.1       agc 		addr.port = (uint16_t) u32;
    278      1.1       agc 
    279      1.1       agc 		/* And each target must have a group tag */
    280      1.1       agc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
    281      1.1       agc 		if (tag != isnst_PGTag || (data_len && data_len != 4)) {
    282      1.1       agc 			DEBOUT(("iSNS Query returned no or invalid group tag (tag=%d, "
    283      1.1       agc 					"length=%d)\n", tag, data_len));
    284      1.1       agc 			isns_free_trans(t);
    285      1.1       agc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
    286      1.1       agc 		}
    287      1.1       agc 		if (data_len) {
    288      1.1       agc 			u32 = ntohl(*((uint32_t *) data_p));
    289      1.1       agc 			addr.group_tag = (uint16_t) u32;
    290      1.1       agc 		} else
    291      1.1       agc 			addr.group_tag = 0;
    292      1.1       agc 
    293      1.1       agc 		/* we have everything necessary to describe the target, add it. */
    294      1.1       agc 
    295      1.1       agc 		DEB(1, ("Adding <%s>, IP <%s>, Port %d, Tag %d\n",
    296      1.1       agc 				name, addr.address, addr.port, addr.group_tag));
    297      1.1       agc 
    298      1.1       agc 		if ((targ = add_discovered_target((unsigned char *)name, &addr, PORTAL_TYPE_ISNS,
    299      1.1       agc 				isns->entry.sid.id)) == NULL) {
    300      1.1       agc 			isns_free_trans(t);
    301      1.1       agc 			return ISCSID_STATUS_NO_RESOURCES;
    302      1.1       agc 		}
    303      1.1       agc 
    304      1.1       agc 		if (alias[0]) {
    305      1.1       agc 			strlcpy((char *)targ->TargetAlias, alias,
    306      1.1       agc 				sizeof(targ->TargetAlias));
    307      1.1       agc 		}
    308      1.1       agc 	}
    309      1.1       agc 	isns_free_trans(t);
    310      1.1       agc 
    311      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    312      1.1       agc }
    313      1.1       agc 
    314      1.1       agc 
    315      1.1       agc /*
    316      1.1       agc  * deregister_isns_server
    317      1.1       agc  *  Support routine to deregister the initiator from the iSNS server
    318      1.1       agc  *
    319      1.1       agc  * Parameters:  The server descriptor
    320      1.1       agc  *
    321      1.1       agc  * Returns:     status
    322      1.1       agc  */
    323      1.1       agc 
    324      1.1       agc static uint32_t
    325      1.1       agc deregister_isns_server(isns_t * isns)
    326      1.1       agc {
    327      1.1       agc 	int retval;
    328      1.1       agc 	ISNS_TRANS t;
    329      1.1       agc 	struct timespec tout = { 5, 0 };
    330      1.1       agc 	uint32_t status;
    331      1.1       agc 
    332      1.1       agc 	/*
    333      1.1       agc 	 * Create transaction for deregistering with iSNS server
    334      1.1       agc 	 */
    335      1.1       agc 
    336      1.1       agc 	if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevDereg,
    337      1.1       agc 												  MY_FLAGS))) {
    338      1.1       agc 		DEBOUT(("dereg_isns_server iscsi_new_trans failed\n"));
    339      1.1       agc 		return ISCSID_STATUS_NO_RESOURCES;
    340      1.1       agc 	}
    341      1.1       agc 
    342      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
    343      1.1       agc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
    344      1.1       agc 	isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
    345      1.2  christos 	isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
    346      1.1       agc 				 isns->reg_ip_addr);
    347      1.2  christos 	isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
    348      1.1       agc 				 &isns->reg_ip_port);
    349      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
    350      1.1       agc 
    351      1.1       agc 	retval = isns_send_trans(t, &tout, &status);
    352      1.1       agc 	DEB(9, ("DevAttrReg request returns %d, status %d\n", retval, status));
    353      1.1       agc 
    354      1.1       agc 	isns_free_trans(t);
    355      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    356      1.1       agc }
    357      1.1       agc 
    358      1.1       agc /*
    359      1.1       agc  * register_isns_server
    360      1.1       agc  *
    361      1.1       agc  * Parameters:  The server descriptor
    362      1.1       agc  *
    363      1.1       agc  * Returns:     status
    364      1.1       agc  */
    365      1.1       agc 
    366      1.1       agc 
    367      1.1       agc static uint32_t
    368      1.1       agc register_isns_server(isns_t * isns)
    369      1.1       agc {
    370      1.1       agc 	int retval;
    371      1.1       agc 	ISNS_TRANS t;
    372      1.1       agc 	uint32_t u32;
    373      1.1       agc 	struct timespec tout = { 5, 0 };
    374      1.1       agc 	uint32_t status;
    375      1.1       agc 
    376      1.1       agc 	if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevAttrReg,
    377      1.1       agc 												  MY_FLAGS))) {
    378      1.1       agc 		DEBOUT(("iscsi_new_trans failed\n"));
    379      1.1       agc 		return ISCSID_STATUS_NO_RESOURCES;
    380      1.1       agc 	}
    381      1.1       agc 
    382      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);	/*tag=32 */
    383      1.1       agc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
    384      1.1       agc 	isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
    385      1.1       agc 	u32 = htonl(2);
    386      1.2  christos 	isns_add_tlv(t, isnst_EntProtocol, (uint32_t)sizeof(u32), &u32);
    387      1.2  christos 	isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
    388      1.1       agc 				 isns->reg_ip_addr);
    389      1.2  christos 	isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
    390      1.1       agc 				 &isns->reg_ip_port);
    391      1.1       agc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);	/*tag=32 */
    392      1.1       agc 	u32 = htonl(2);
    393      1.2  christos 	isns_add_tlv(t, isnst_iSCSINodeType, (uint32_t)sizeof(u32), &u32);
    394      1.1       agc 		/*tag=33 (node type = intiator) */
    395      1.1       agc 
    396      1.1       agc 	retval = isns_send_trans(t, &tout, &status);
    397      1.1       agc 	DEB(9, ("DevAttrReg request returns %d, status %d\n", retval, status));
    398      1.1       agc 	isns_free_trans(t);
    399      1.1       agc 
    400      1.1       agc 	if (retval || status)
    401      1.1       agc 		return ISCSID_STATUS_ISNS_ERROR;
    402      1.1       agc 
    403      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    404      1.1       agc }
    405      1.1       agc 
    406      1.1       agc 
    407      1.1       agc /*
    408      1.1       agc  * get_registration_info
    409      1.1       agc  *
    410      1.1       agc  * Parameters:  The server descriptor
    411      1.1       agc  *
    412      1.1       agc  * Returns:     status
    413      1.1       agc  */
    414      1.1       agc 
    415      1.1       agc 
    416      1.1       agc static uint32_t
    417      1.1       agc get_registration_info(isns_t * isns)
    418      1.1       agc {
    419      1.1       agc 	struct sockaddr_storage sa;
    420      1.1       agc 	unsigned n;
    421      1.1       agc 
    422      1.1       agc 	strlcpy((char *)isns->reg_iscsi_name, (char *)node_name.InitiatorName,
    423      1.1       agc 			sizeof(isns->reg_iscsi_name));
    424      1.1       agc 	strlcpy((char *)isns->reg_entity_id, (char *)node_name.InitiatorAlias,
    425      1.1       agc 			sizeof(isns->reg_entity_id));
    426      1.1       agc 
    427      1.1       agc 	/*Get our source IP and port numbers */
    428      1.1       agc 	n = sizeof(sa);
    429      1.2  christos 	if (getsockname(isns->sock, (struct sockaddr *)(void *)&sa, &n)) {
    430      1.1       agc 		DEBOUT(("Getsockname returned error %d\n", errno));
    431      1.1       agc 		return ISCSID_STATUS_GENERAL_ERROR;
    432      1.1       agc 	}
    433      1.1       agc 	switch (sa.ss_family) {
    434      1.1       agc 	case AF_INET:
    435      1.1       agc 		{
    436      1.2  christos 			struct sockaddr_in *si =
    437      1.2  christos 			    (struct sockaddr_in *)(void *)&sa;
    438      1.2  christos 			uint32_t *u32 = (uint32_t *)(void *)isns->reg_ip_addr;
    439      1.1       agc 
    440      1.1       agc 			u32[0] = u32[1] = 0;
    441      1.1       agc 			u32[2] = htonl(0xffff);
    442      1.1       agc 			u32[3] = htonl(si->sin_addr.s_addr);
    443      1.1       agc 			isns->reg_ip_port = htons(si->sin_port);
    444      1.1       agc 		}
    445      1.1       agc 		break;
    446      1.1       agc 
    447      1.1       agc 	case AF_INET6:
    448      1.1       agc 		{
    449      1.2  christos 			struct sockaddr_in6 *si =
    450      1.2  christos 			    (struct sockaddr_in6 *)(void *) &sa;
    451      1.1       agc 
    452      1.1       agc 			memcpy(isns->reg_ip_addr, &si->sin6_addr,
    453      1.1       agc 					sizeof(isns->reg_ip_addr));
    454      1.1       agc 			isns->reg_ip_port = htons(si->sin6_port);
    455      1.1       agc 		}
    456      1.1       agc 		break;
    457      1.1       agc 
    458      1.1       agc 	default:
    459      1.1       agc 		DEBOUT(("Getsockname returned unknown address family: %d\n",
    460      1.1       agc 				sa.ss_family));
    461      1.1       agc 		return ISCSID_STATUS_GENERAL_ERROR;
    462      1.1       agc 	}
    463      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    464      1.1       agc }
    465      1.1       agc 
    466      1.1       agc 
    467      1.1       agc /*
    468      1.1       agc  * iscsi_isns_serverconn - given a set of server address, try connecting
    469      1.1       agc  *
    470      1.1       agc  * Parameters:  The descriptor for the iSNS server to query
    471      1.1       agc  *
    472      1.1       agc  * Returns:     status
    473      1.1       agc  */
    474      1.1       agc 
    475      1.1       agc static uint32_t
    476      1.1       agc iscsi_isns_serverconn(isns_t * isns)
    477      1.1       agc {
    478      1.1       agc 	int sock = -1;
    479      1.1       agc 	char port[16];
    480      1.1       agc 	struct addrinfo hints;
    481      1.1       agc 	struct addrinfo *ai, *addr;
    482      1.1       agc 	int retval;
    483      1.1       agc 
    484      1.1       agc 	/*
    485      1.1       agc 	 * Initialize the iSNS library if it needs it
    486      1.1       agc 	 */
    487      1.1       agc 
    488      1.1       agc 	if (isns_handle == ISNS_INVALID_HANDLE) {
    489      1.1       agc 		if ((retval = isns_init(&isns_handle, 0)) != 0) {
    490      1.1       agc 			/*Couldn't initialize the iSNS library */
    491      1.1       agc 			DEBOUT(("isns_init failed with code %d\n", retval));
    492      1.1       agc 			isns_handle = ISNS_INVALID_HANDLE;
    493      1.1       agc 			return ISCSID_STATUS_GENERAL_ERROR;
    494      1.1       agc 		}
    495      1.1       agc 	}
    496      1.1       agc 
    497      1.1       agc 	/*
    498      1.1       agc 	 * Find the server address from the iSNS server list entry,
    499      1.1       agc 	 * and try to connect to the iSNS server
    500      1.1       agc 	 */
    501      1.1       agc 
    502      1.1       agc 	snprintf(port, sizeof(port), "%d", (isns->port) ? isns->port : ISCSI_DEFAULT_ISNS_PORT);
    503      1.1       agc 	memset(&hints, 0, sizeof(hints));
    504      1.1       agc 	hints.ai_family = PF_UNSPEC;
    505      1.1       agc 	hints.ai_socktype = SOCK_STREAM;
    506      1.1       agc 	hints.ai_protocol = IPPROTO_TCP;
    507      1.1       agc 
    508      1.1       agc 	retval = getaddrinfo((char *)isns->address, port, &hints, &ai);
    509      1.1       agc 	if (retval) {
    510      1.1       agc 		DEBOUT(("getaddrinfo failed with code %d (%s)\n",
    511      1.1       agc 				retval, gai_strerror(retval)));
    512      1.1       agc 		return ISCSID_STATUS_GENERAL_ERROR;
    513      1.1       agc 	}
    514      1.1       agc 
    515      1.1       agc 	for (addr = ai; addr != NULL; addr = addr->ai_next) {
    516      1.2  christos 		sock = socket(addr->ai_family, addr->ai_socktype,
    517      1.2  christos 		    addr->ai_protocol);
    518      1.1       agc 
    519      1.2  christos 		if (sock == -1) {
    520      1.2  christos 			DEBOUT(("%s: socket call FAILED!\n", __func__));
    521      1.1       agc 			freeaddrinfo(ai);
    522      1.2  christos 			return (uint32_t)-1;
    523      1.1       agc 		}
    524      1.1       agc 
    525  1.3.2.1       jdc 		if (connect(sock, addr->ai_addr, addr->ai_addrlen) != -1)
    526      1.1       agc 			break;
    527      1.1       agc 
    528      1.2  christos 		DEB(1, ("%s: connect call FAILED!\n", __func__));
    529      1.1       agc 		close(sock);
    530      1.1       agc 		sock = -1;
    531      1.1       agc 	}
    532      1.1       agc 
    533      1.1       agc 	if (addr == NULL) {
    534      1.2  christos 		DEBOUT(("%s: couldn't connect!\n", __func__));
    535      1.1       agc 		freeaddrinfo(ai);
    536      1.1       agc 		return ISCSID_STATUS_GENERAL_ERROR;
    537      1.1       agc 	}
    538      1.1       agc 
    539      1.1       agc 	if (isns_add_servercon(isns_handle, sock, addr)) {
    540      1.2  christos 		DEBOUT(("%s: FAILED!\n", __func__));
    541      1.1       agc 		close(sock);
    542      1.1       agc 		freeaddrinfo(ai);
    543      1.1       agc 		return ISCSID_STATUS_GENERAL_ERROR;
    544      1.1       agc 	}
    545      1.1       agc 
    546      1.1       agc 	freeaddrinfo(ai);
    547      1.1       agc 	isns->sock = sock;
    548      1.1       agc 
    549      1.1       agc 	if ((retval = get_registration_info(isns)) != 0) {
    550      1.1       agc 		return retval;
    551      1.1       agc 	}
    552      1.1       agc 
    553      1.1       agc 	deregister_isns_server(isns);
    554      1.1       agc 
    555      1.1       agc 	return register_isns_server(isns);
    556      1.1       agc }
    557      1.1       agc 
    558      1.1       agc 
    559      1.1       agc /*
    560      1.1       agc  * update_isns_server_info
    561      1.1       agc  *  Support routine to query the specified iSNS server for all targets
    562      1.1       agc  *  Called from add_isns_server and refresh_isns_server
    563      1.1       agc  *
    564      1.1       agc  * Parameters:  The descriptor for the iSNS server to query
    565      1.1       agc  *
    566      1.1       agc  * Returns:     status
    567      1.1       agc  */
    568      1.1       agc 
    569      1.1       agc 
    570      1.1       agc static uint32_t
    571      1.1       agc update_isns_server_info(isns_t * isns)
    572      1.1       agc {
    573      1.1       agc 	int retval;
    574      1.1       agc 	ISNS_TRANS t;
    575      1.1       agc 	uint32_t tag;
    576      1.2  christos 	uint32_t data_len;
    577      1.1       agc 	void *data_p;
    578      1.1       agc 	uint32_t u32;
    579      1.1       agc 	struct timespec tout = { 5, 0 };
    580      1.1       agc 	uint32_t status;
    581      1.1       agc 	uint8_t TargetName[ISCSI_STRING_LENGTH];
    582      1.1       agc 
    583      1.1       agc 
    584      1.1       agc 	DEB(9, ("update_isns_server_info for iSNS %s\n", isns->address));
    585      1.1       agc 
    586      1.1       agc 	if (isns->sock < 0) {
    587      1.1       agc 		if ((status = iscsi_isns_serverconn(isns)) != 0) {
    588      1.1       agc 			/*We couldn't connect to the iSNS server */
    589      1.1       agc 			DEB(9, ("update_isns_server_info iscsi_isns_serverconn failed\n"));
    590      1.1       agc 			return status;
    591      1.1       agc 		}
    592      1.1       agc 	}
    593      1.1       agc 
    594      1.1       agc 	for (TargetName[0] = 0;;) {
    595      1.1       agc 		if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle,
    596      1.1       agc 												isnsp_DevGetNext, MY_FLAGS))) {
    597      1.1       agc 			DEBOUT(("update_isns_server_info iscsi_new_trans failed\n"));
    598      1.1       agc 			return ISCSID_STATUS_NO_RESOURCES;
    599      1.1       agc 		}
    600      1.1       agc 
    601      1.1       agc 		isns_add_string(t, isnst_iSCSIName, (char *)node_name.InitiatorName);
    602      1.1       agc 
    603      1.1       agc 		if (TargetName[0])
    604      1.1       agc 			isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
    605      1.1       agc 		else
    606      1.1       agc 			isns_add_tlv(t, isnst_iSCSIName, 0, NULL);
    607      1.1       agc 
    608      1.1       agc 		isns_add_tlv(t, isnst_Delimiter, 0, NULL);
    609      1.1       agc 		isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL);
    610      1.1       agc 
    611      1.1       agc 		if ((retval = isns_send_trans(t, &tout, &status)) != 0) {
    612      1.1       agc 			DEBOUT(("isns_send_trans returns rc %d, status %d\n",
    613      1.1       agc 					retval, status));
    614      1.1       agc 			isns_free_trans(t);
    615      1.1       agc 			break;
    616      1.1       agc 		}
    617      1.1       agc 		if (status) {
    618      1.1       agc 			DEB(9, ("DevGetNext Status = %d\n", status));
    619      1.1       agc 			break;
    620      1.1       agc 		}
    621      1.1       agc 
    622      1.1       agc 		if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
    623      1.1       agc 			DEBOUT(("No TLV in DevGetNext response!\n"));
    624      1.1       agc 			isns_free_trans(t);
    625      1.1       agc 			break;
    626      1.1       agc 		}
    627      1.1       agc 		/* We need the name, or there's nothing left to do */
    628      1.1       agc 
    629      1.1       agc 		if (tag != isnst_iSCSIName || !data_len ||
    630      1.1       agc 			data_len >= ISCSI_STRING_LENGTH) {
    631      1.1       agc 			DEBOUT(("iSNS GetNextDev returned no or invalid name (tag=%d, "
    632      1.1       agc 					"length=%d)\n", tag, data_len));
    633      1.1       agc 			isns_free_trans(t);
    634      1.1       agc 			break;
    635      1.1       agc 		}
    636      1.1       agc 		strlcpy((char *)TargetName, (char *) data_p, sizeof(TargetName));
    637      1.1       agc 
    638      1.1       agc 		/* We must get at least the node type, and it must be a target */
    639      1.1       agc 		if (isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
    640      1.1       agc 			DEBOUT(("iSNS GetDevNext did not return node type\n"));
    641      1.1       agc 			isns_free_trans(t);
    642      1.1       agc 			break;
    643      1.1       agc 		}
    644      1.1       agc 		if (tag == isnst_Delimiter && isns_get_tlv(t, ISNS_TLV_NEXT, &tag,
    645      1.1       agc 													&data_len, &data_p)) {
    646      1.1       agc 			DEBOUT(("iSNS GetDevNext did not return node type (past delim)\n"));
    647      1.1       agc 			isns_free_trans(t);
    648      1.1       agc 			break;
    649      1.1       agc 		}
    650      1.1       agc 		if (tag != isnst_iSCSINodeType || data_len != 4) {
    651      1.1       agc 			DEBOUT(("iSNS Query returned no or invalid node type (tag=%d, "
    652      1.1       agc 					"length=%d)\n", tag, data_len));
    653      1.1       agc 			isns_free_trans(t);
    654      1.1       agc 			break;
    655      1.1       agc 		}
    656      1.1       agc 		u32 = ntohl(*((uint32_t *) data_p));
    657      1.1       agc 		isns_free_trans(t);
    658      1.1       agc 
    659      1.1       agc 		if (u32 & 1)
    660      1.1       agc 			get_isns_target_info(isns, TargetName);
    661      1.1       agc 	}
    662      1.1       agc 
    663      1.1       agc 	DEB(9, ("update_isns_server_info returning SUCCESS!\n"));
    664      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    665      1.1       agc }
    666      1.1       agc 
    667      1.1       agc 
    668      1.1       agc /**********************************************************************
    669      1.1       agc **********************************************************************/
    670      1.1       agc 
    671      1.1       agc /*
    672      1.1       agc  * create_isns:
    673      1.1       agc  *    Create an isns structure and initialize it.
    674      1.1       agc  *
    675      1.1       agc  *    Parameter:
    676      1.1       agc  *          name        The iSNS server name
    677      1.1       agc  *
    678      1.1       agc  *    Returns:    Pointer to isns structure, NULL if allocation failed.
    679      1.1       agc  */
    680      1.1       agc 
    681      1.3       agc static isns_t *
    682      1.1       agc create_isns(iscsid_add_isns_server_req_t * req)
    683      1.1       agc {
    684      1.1       agc 	isns_t *isns;
    685      1.1       agc 
    686      1.1       agc 	DEB(9, ("Create iSNS %s\n", req->address));
    687      1.1       agc 
    688      1.1       agc 	if ((isns = calloc(1, sizeof(*isns))) == NULL)
    689      1.1       agc 		return NULL;
    690      1.1       agc 
    691      1.1       agc 	for (isns_id++; !isns_id || find_isns_id(isns_id) != NULL;)
    692      1.1       agc 		isns_id++;
    693      1.1       agc 
    694      1.1       agc 	isns->entry.sid.id = isns_id;
    695      1.1       agc 	strlcpy((char *)isns->entry.sid.name, (char *)req->name, sizeof(isns->entry.sid.name));
    696      1.1       agc 	strlcpy((char *)isns->address, (char *)req->address, sizeof(isns->address));
    697      1.1       agc 	isns->port = req->port;
    698      1.1       agc 	isns->sock = -1;
    699      1.1       agc 
    700      1.1       agc 	return isns;
    701      1.1       agc }
    702      1.1       agc 
    703      1.1       agc 
    704      1.1       agc /*
    705      1.1       agc  * add_isns_server
    706      1.1       agc  *    Adds an iSNS server to the server list.
    707      1.1       agc  *    This command will add the address of an iSNS server to the list
    708      1.1       agc  *      of iSNS servers that the discovery daemon queries to discover targets.
    709      1.1       agc  *      The daemon will then register itself with the iSNS server,
    710      1.1       agc  *      and query the iSNS server for the list of targets.
    711      1.1       agc  *      The discovered targets will be added to the list of target portals.
    712      1.1       agc  *      The response contains the ID of the iSNS server.
    713      1.1       agc  *
    714      1.1       agc  * Parameter:  The parameter contains the address of the server.
    715      1.1       agc  *
    716      1.1       agc  * Returns:    Nothing
    717      1.1       agc  *             The response parameter is an iscsid_add_isns_server_rsp_t
    718      1.1       agc  *             containing:
    719      1.1       agc  *                  server_id = Unique ID for the iSNS server
    720      1.1       agc  */
    721      1.1       agc 
    722      1.1       agc void
    723      1.1       agc add_isns_server(iscsid_add_isns_server_req_t * req, iscsid_response_t ** prsp,
    724      1.1       agc 				int *prsp_temp)
    725      1.1       agc {
    726      1.1       agc 	iscsid_response_t *rsp = *prsp;
    727      1.1       agc 	iscsid_add_isns_server_rsp_t *res;
    728      1.1       agc 	isns_t *isns;
    729      1.1       agc 
    730      1.1       agc 	DEB(9, ("IN add_isns_server\n"));
    731      1.1       agc 
    732      1.1       agc 	/*
    733      1.1       agc 	 * Make a response
    734      1.1       agc 	 */
    735      1.1       agc 
    736      1.1       agc 	rsp = make_rsp(sizeof(iscsid_add_isns_server_rsp_t), prsp, prsp_temp);
    737      1.1       agc 	if (rsp == NULL) {
    738      1.1       agc 		DEB(9, ("OUT add_isns_server: make_rsp FAILED\n"));
    739      1.1       agc 		return;
    740      1.1       agc 	}
    741      1.1       agc 
    742      1.2  christos 	res = (iscsid_add_isns_server_rsp_t *)(void *)rsp->parameter;
    743      1.1       agc 
    744      1.1       agc 	/*
    745      1.1       agc 	 * First, allocate the isns server structure to put on the list
    746      1.1       agc 	 */
    747      1.1       agc 
    748      1.1       agc 	isns = create_isns(req);
    749      1.1       agc 	if (isns == NULL) {
    750      1.1       agc 		rsp->status = ISCSID_STATUS_NO_RESOURCES;
    751      1.1       agc 		DEB(9, ("OUT add_isns_server: create_isns FAILED!\n"));
    752      1.1       agc 		return;
    753      1.1       agc 	}
    754      1.1       agc 
    755      1.1       agc 	TAILQ_INSERT_TAIL(&list[ISNS_LIST].list, &isns->entry, link);
    756      1.1       agc 	list[ISNS_LIST].num_entries++;
    757      1.1       agc 	res->server_id = isns->entry.sid.id;
    758      1.1       agc 
    759      1.1       agc 	DEB(9, ("OUT add_isns_server: server_id = %d, name = %s\n",
    760      1.1       agc 			isns->entry.sid.id, isns->address));
    761      1.1       agc 
    762      1.1       agc 	/*
    763      1.1       agc 	 * Now try to connect to the iSNS server...
    764      1.1       agc 	 */
    765      1.1       agc 
    766      1.1       agc 	update_isns_server_info(isns);
    767      1.1       agc }
    768      1.1       agc 
    769      1.1       agc 
    770      1.1       agc /*
    771      1.1       agc  * get_isns_server
    772      1.1       agc  *    Returns the address of the iSNS server with the specified ID
    773      1.1       agc  *
    774      1.1       agc  * Parameters:  The unique ID of the server
    775      1.1       agc  *
    776      1.1       agc  * Returns:     The status returned by the driver
    777      1.1       agc  *              The response parameter contains the iSNS server address as a
    778      1.1       agc  *              zero-terminated UTF-8 string
    779      1.1       agc  */
    780      1.1       agc 
    781      1.1       agc void
    782      1.1       agc get_isns_server(iscsid_sym_id_t * preq, iscsid_response_t ** prsp,
    783      1.1       agc 				int *prsp_temp)
    784      1.1       agc {
    785      1.1       agc 	iscsid_response_t *rsp = *prsp;
    786      1.1       agc 	iscsid_get_isns_server_rsp_t *res;
    787      1.1       agc 	isns_t *isns;
    788      1.1       agc 
    789      1.1       agc 	DEB(9, ("IN get_isns_server\n"));
    790      1.1       agc 	isns = find_isns(preq);
    791      1.1       agc 	if (isns == NULL) {
    792      1.1       agc 		rsp->status = ISCSID_STATUS_INVALID_ISNS_ID;
    793      1.1       agc 		DEB(9, ("OUT get_isns_server: find_isns FAILED!\n"));
    794      1.1       agc 		return;
    795      1.1       agc 	}
    796      1.1       agc 
    797      1.1       agc 	rsp = make_rsp(sizeof(iscsid_get_isns_server_rsp_t), prsp, prsp_temp);
    798      1.1       agc 	if (rsp == NULL) {
    799      1.1       agc 		DEB(9, ("OUT get_isns_server: make_rsp FAILED!\n"));
    800      1.1       agc 		return;
    801      1.1       agc 	}
    802      1.2  christos 	res = (iscsid_get_isns_server_rsp_t *)(void *)rsp->parameter;
    803      1.1       agc 
    804      1.2  christos 	strlcpy((char *)res->address, (char *)isns->address,
    805      1.2  christos 	    sizeof(res->address));
    806      1.1       agc 	res->port = isns->port;
    807      1.1       agc 	res->server_id = isns->entry.sid;
    808      1.1       agc 	DEB(9, ("OUT get_isns_server: id = %d, address = %s\n",
    809      1.1       agc 			res->server_id.id, res->address));
    810      1.1       agc }
    811      1.1       agc 
    812      1.1       agc 
    813      1.1       agc /*
    814      1.1       agc  * slp_find_isns_servers
    815      1.1       agc  */
    816      1.1       agc 
    817      1.1       agc /* More Here Later... */
    818      1.1       agc 
    819      1.1       agc 
    820      1.1       agc /*
    821      1.1       agc  * refresh_isns_server
    822      1.1       agc  *    Query the specified iSNS servers for the list of targets.
    823      1.1       agc  *
    824      1.1       agc  *    Parameters:
    825      1.1       agc  *          id    Server ID
    826      1.1       agc  *
    827      1.1       agc  *    Returns:     Status
    828      1.1       agc  */
    829      1.1       agc 
    830      1.1       agc uint32_t
    831      1.1       agc refresh_isns_server(uint32_t id)
    832      1.1       agc {
    833      1.1       agc 	uint32_t rc;
    834      1.1       agc 	isns_t *isns;
    835      1.1       agc 	generic_entry_t *curr;
    836      1.1       agc 	generic_entry_t *next;
    837      1.1       agc 
    838      1.1       agc 	isns = find_isns_id(id);
    839      1.1       agc 	if (isns == NULL)
    840      1.1       agc 		return ISCSID_STATUS_INVALID_ISNS_ID;
    841      1.1       agc 
    842      1.1       agc 	TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
    843      1.2  christos 		portal_t *p = (portal_t *)(void *)curr;
    844      1.2  christos 		if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
    845      1.2  christos 			p->portaltype = PORTAL_TYPE_REFRESHING;
    846      1.1       agc 	}
    847      1.1       agc 
    848      1.1       agc 	rc = update_isns_server_info(isns);
    849      1.1       agc 
    850      1.1       agc 	/*
    851      1.1       agc 	 * Go through our list of portals and look for ones
    852      1.1       agc 	 * that are still marked for refreshing.
    853      1.1       agc 	 * These are ones that are no longer there and should be removed.
    854      1.1       agc 	 */
    855      1.1       agc 
    856      1.1       agc 	for (curr = TAILQ_FIRST(&list[PORTAL_LIST].list); curr != NULL;
    857      1.1       agc 		 curr = next) {
    858      1.2  christos 		portal_t *p = (portal_t *)(void *)curr;
    859      1.1       agc 		next = TAILQ_NEXT(curr, link);
    860      1.2  christos 		if (p->portaltype == PORTAL_TYPE_REFRESHING)
    861      1.2  christos 			delete_portal(p, TRUE);
    862      1.1       agc 	}
    863      1.1       agc 
    864      1.1       agc 	return rc;
    865      1.1       agc }
    866      1.1       agc 
    867      1.1       agc 
    868      1.1       agc /*
    869      1.1       agc  * remove_isns_server
    870      1.1       agc  *    Removed an iSNS server.
    871      1.1       agc  *    This does not remove the discovered targets from the list.
    872      1.1       agc  *
    873      1.1       agc  * Parameters:  The iscid_remove_isns_req_t structure containing:
    874      1.1       agc  *                  server_id = unique ID of server to remove
    875      1.1       agc  *
    876      1.1       agc  * Returns:     The status returned.
    877      1.1       agc  */
    878      1.1       agc 
    879      1.1       agc uint32_t
    880      1.1       agc remove_isns_server(iscsid_sym_id_t * preq)
    881      1.1       agc {
    882      1.1       agc 	generic_entry_t *curr;
    883      1.1       agc 	isns_t *isns;
    884      1.1       agc 	uint32_t id;
    885      1.1       agc 
    886      1.1       agc 	isns = find_isns(preq);
    887      1.1       agc 	if (isns == NULL)
    888      1.1       agc 		return ISCSID_STATUS_INVALID_ISNS_ID;
    889      1.1       agc 
    890      1.1       agc 	/*Deregister with the iSNS server. */
    891      1.1       agc 	/*Ignore any errors during deregistration... */
    892      1.1       agc 	if (isns->sock >= 0) {
    893      1.1       agc 		deregister_isns_server(isns);
    894      1.1       agc 		close(isns->sock);
    895      1.1       agc 	}
    896      1.1       agc 
    897      1.1       agc 	TAILQ_REMOVE(&list[ISNS_LIST].list, &isns->entry, link);
    898      1.1       agc 	list[ISNS_LIST].num_entries--;
    899      1.1       agc 
    900      1.1       agc 	id = isns->entry.sid.id;
    901      1.1       agc 	free(isns);
    902      1.1       agc 
    903      1.1       agc 	TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
    904      1.2  christos 		portal_t *p = (portal_t *)(void *)curr;
    905      1.2  christos 		if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
    906      1.2  christos 			p->discoveryid = 0; /* mark deleted */
    907      1.1       agc 	}
    908      1.1       agc 
    909      1.1       agc 	return ISCSID_STATUS_SUCCESS;
    910      1.1       agc }
    911      1.1       agc 
    912      1.1       agc 
    913      1.1       agc /*
    914      1.1       agc    Deregister all isns servers on daemon termination
    915      1.1       agc */
    916      1.1       agc 
    917      1.1       agc void
    918      1.1       agc dereg_all_isns_servers(void)
    919      1.1       agc {
    920      1.1       agc 	generic_list_t *plist;
    921      1.1       agc 	generic_entry_t *curr;
    922      1.1       agc 
    923      1.1       agc 	plist = &list[ISNS_LIST].list;
    924      1.1       agc 	TAILQ_FOREACH(curr, plist, link)
    925      1.2  christos 		deregister_isns_server((isns_t *)(void *)curr);
    926      1.1       agc }
    927      1.1       agc 
    928      1.1       agc #endif
    929      1.1       agc 
    930