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