xref: /netbsd-src/sbin/iscsid/iscsid_discover.c (revision 6fea88c26e5bb459c67a7e5e4e975fd6abe5050a)
1*6fea88c2Smlelstv /*	$NetBSD: iscsid_discover.c,v 1.5 2016/05/29 13:35:45 mlelstv Exp $	*/
275a17f3cSagc 
375a17f3cSagc /*-
475a17f3cSagc  * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
575a17f3cSagc  * All rights reserved.
675a17f3cSagc  *
775a17f3cSagc  * This code is derived from software contributed to The NetBSD Foundation
875a17f3cSagc  * by Wasabi Systems, Inc.
975a17f3cSagc  *
1075a17f3cSagc  * Redistribution and use in source and binary forms, with or without
1175a17f3cSagc  * modification, are permitted provided that the following conditions
1275a17f3cSagc  * are met:
1375a17f3cSagc  * 1. Redistributions of source code must retain the above copyright
1475a17f3cSagc  *    notice, this list of conditions and the following disclaimer.
1575a17f3cSagc  * 2. Redistributions in binary form must reproduce the above copyright
1675a17f3cSagc  *    notice, this list of conditions and the following disclaimer in the
1775a17f3cSagc  *    documentation and/or other materials provided with the distribution.
1875a17f3cSagc  *
1975a17f3cSagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2075a17f3cSagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2175a17f3cSagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2275a17f3cSagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2375a17f3cSagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2475a17f3cSagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2575a17f3cSagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2675a17f3cSagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2775a17f3cSagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2875a17f3cSagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2975a17f3cSagc  * POSSIBILITY OF SUCH DAMAGE.
3075a17f3cSagc  */
3175a17f3cSagc 
3275a17f3cSagc #ifndef ISCSI_MINIMAL
3375a17f3cSagc 
3475a17f3cSagc #include "iscsid_globals.h"
3575a17f3cSagc #include "isns.h"
3675a17f3cSagc #include "isns_defs.h"
3775a17f3cSagc 
3875a17f3cSagc #include <sys/socket.h>
3975a17f3cSagc #include <netinet/in.h>
4075a17f3cSagc #include <netinet/tcp.h>
4175a17f3cSagc #include <netdb.h>
4275a17f3cSagc 
4375a17f3cSagc #define MY_FLAGS  ISNS_FLAG_REPLACE_REG
4475a17f3cSagc 
4575a17f3cSagc 
4675a17f3cSagc /**********************************************************************
4775a17f3cSagc **********************************************************************/
4875a17f3cSagc 
4975a17f3cSagc uint32_t isns_id = 0;			/* isns ID counter */
5075a17f3cSagc 
5175a17f3cSagc ISNS_HANDLE isns_handle = ISNS_INVALID_HANDLE;
5275a17f3cSagc 
5375a17f3cSagc /**********************************************************************
5475a17f3cSagc **********************************************************************/
5575a17f3cSagc 
5675a17f3cSagc /*
5775a17f3cSagc  * xlate_ip
5875a17f3cSagc  *  Support routine to translate binary IP into string form for storage in
5975a17f3cSagc  *  target object. Handles IPv6 and IPv4 formats.
6075a17f3cSagc  *
6175a17f3cSagc  * Parameters:
6275a17f3cSagc  *       dest  the destination string
6375a17f3cSagc  *       data  the source (from iSNS address field)
6475a17f3cSagc  *
6575a17f3cSagc  * Returns:     status
6675a17f3cSagc  */
6775a17f3cSagc 
6838a27f5aSagc static void
xlate_ip(uint8_t * dest,size_t size,void * data)69f7720048Schristos xlate_ip(uint8_t *dest, size_t size, void *data)
7075a17f3cSagc {
7175a17f3cSagc 	uint16_t *wdt = (uint16_t *) data;
7275a17f3cSagc 	size_t	cc;
7375a17f3cSagc 	int i;
74f7720048Schristos 	char *dst = (char *)dest;
75f7720048Schristos 	char *dt = data;
7675a17f3cSagc 
7775a17f3cSagc 	for (i = 0; i < 5 && !wdt[i]; i++) {
7875a17f3cSagc 	}
7975a17f3cSagc 	if (i == 5 && wdt[5] == 0xffff) {
80f7720048Schristos 		snprintf(dst, size, "%d.%d.%d.%d",
81f7720048Schristos 			dt[12], dt[13], dt[14], dt[15]);
8275a17f3cSagc 	} else {
8375a17f3cSagc 		for (cc = 0, i = 0; i < 7; i++) {
84f7720048Schristos 			cc += snprintf(&dst[cc], size - cc, "%x:", wdt[i]);
8575a17f3cSagc 		}
86f7720048Schristos 		snprintf(&dst[cc], size - cc, "%x", wdt[7]);
8775a17f3cSagc 	}
8875a17f3cSagc }
8975a17f3cSagc 
9075a17f3cSagc 
9175a17f3cSagc /*
9275a17f3cSagc  * get_isns_target_info
9375a17f3cSagc  *  Support routine to query the server for the attributes of the given target.
9475a17f3cSagc  *
9575a17f3cSagc  * Parameters:
9675a17f3cSagc  *       TargetName  The target name to query.
9775a17f3cSagc  *
9875a17f3cSagc  * Returns:     status
9975a17f3cSagc  */
10075a17f3cSagc 
10138a27f5aSagc static uint32_t
get_isns_target_info(isns_t * isns,uint8_t * TargetName)10275a17f3cSagc get_isns_target_info(isns_t * isns, uint8_t * TargetName)
10375a17f3cSagc {
10475a17f3cSagc 	int retval;
10575a17f3cSagc 	ISNS_TRANS t;
10675a17f3cSagc 	uint32_t tag;
107f7720048Schristos 	uint32_t data_len;
10875a17f3cSagc 	void *data_p;
10975a17f3cSagc 	uint32_t u32;
11075a17f3cSagc 	struct timespec tout = { 5, 0 };
11175a17f3cSagc 	uint32_t status;
11275a17f3cSagc 	target_t *targ;
11375a17f3cSagc 	char name[ISCSI_STRING_LENGTH];
11475a17f3cSagc 	char alias[ISCSI_STRING_LENGTH];
11575a17f3cSagc 	iscsi_portal_address_t addr;
11675a17f3cSagc 
117f7720048Schristos 	t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS);
118f7720048Schristos 	if (ISNS_INVALID_TRANS == t) {
119*6fea88c2Smlelstv 		DEB(10,("%s: get_targets iscsi_new_trans failed", __func__));
12075a17f3cSagc 		return ISCSID_STATUS_NO_RESOURCES;
12175a17f3cSagc 	}
12275a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
12375a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
12475a17f3cSagc 
12575a17f3cSagc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
12675a17f3cSagc 
12775a17f3cSagc 	isns_add_tlv(t, isnst_iSCSIName, 0, NULL);	/* 32: name */
12875a17f3cSagc 	isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL);	/* 33: node type */
12975a17f3cSagc 	isns_add_tlv(t, isnst_iSCSIAlias, 0, NULL);	/* 34: alias */
13075a17f3cSagc 	/* ToDo: get security attributes... */
13175a17f3cSagc 	/* isns_add_tlv (t, isnst_PortalSecBmap, 0, NULL); */
13275a17f3cSagc 	/*tag=27: security bitmap */
13375a17f3cSagc 
13475a17f3cSagc 	retval = isns_send_trans(t, &tout, &status);
135*6fea88c2Smlelstv 	DEB(9, ("isns_send_trans called, returns %d, status %d", retval, status));
13675a17f3cSagc 	if (retval) {
137*6fea88c2Smlelstv 		DEB(10,("iSNS Attribute Query failed, rc = %d", retval));
13875a17f3cSagc 		isns_free_trans(t);
13975a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
14075a17f3cSagc 	}
14175a17f3cSagc 	/* First is target name (the one we put in), ignore */
14275a17f3cSagc 	if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
143*6fea88c2Smlelstv 		DEB(10,("iSNS Attribute Query returned nothing"));
14475a17f3cSagc 		isns_free_trans(t);
14575a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
14675a17f3cSagc 	}
14775a17f3cSagc 	if (tag != isnst_iSCSIName) {
148*6fea88c2Smlelstv 		DEB(10,("iSNS Query returned bad type (tag = %d, length = %d)",
14975a17f3cSagc 				tag, data_len));
15075a17f3cSagc 		isns_free_trans(t);
15175a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
15275a17f3cSagc 	}
15375a17f3cSagc 
15475a17f3cSagc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
15575a17f3cSagc 	if (tag != isnst_Delimiter) {
156*6fea88c2Smlelstv 		DEB(10,("Attr Query Missing Delimiter (tag = %d, length = %d)",
15775a17f3cSagc 				tag, data_len));
15875a17f3cSagc 		isns_free_trans(t);
15975a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
16075a17f3cSagc 	}
16175a17f3cSagc 
16275a17f3cSagc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
16375a17f3cSagc 	if (tag != isnst_iSCSIName || !data_len || data_len >= ISCSI_STRING_LENGTH) {
164*6fea88c2Smlelstv 		DEB(10,("iSNS Query returned no or invalid name (tag = %d, "
165*6fea88c2Smlelstv 				"length = %d)", tag, data_len));
16675a17f3cSagc 		isns_free_trans(t);
16775a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
16875a17f3cSagc 	}
16975a17f3cSagc 	strlcpy(name, (char *) data_p, sizeof(name));
17075a17f3cSagc 
17175a17f3cSagc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
17275a17f3cSagc 	if (tag != isnst_iSCSINodeType || data_len != 4) {
173*6fea88c2Smlelstv 		DEB(10,("iSNS Query returned no or invalid node type (tag = %d, "
174*6fea88c2Smlelstv 				"length = %d)", tag, data_len));
17575a17f3cSagc 		isns_free_trans(t);
17675a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
17775a17f3cSagc 	}
17875a17f3cSagc 	u32 = ntohl(*((uint32_t *) data_p));
17975a17f3cSagc 	if (!(u32 & 1)) {
180*6fea88c2Smlelstv 		DEB(10,("iSNS Query returned bad type (type=%x, should be 1)", u32));
18175a17f3cSagc 		isns_free_trans(t);
18275a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
18375a17f3cSagc 	}
18475a17f3cSagc 
18575a17f3cSagc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
18675a17f3cSagc 	if (tag == isnst_iSCSIAlias) {
18775a17f3cSagc 		if (data_len >= ISCSI_STRING_LENGTH) {
188*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned invalid alias (tag=%d, length=%d)",
18975a17f3cSagc 					tag, data_len));
19075a17f3cSagc 			isns_free_trans(t);
19175a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
19275a17f3cSagc 		}
19375a17f3cSagc 		strlcpy(alias, (char *) data_p, sizeof(alias));
19475a17f3cSagc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
19575a17f3cSagc 	} else
19675a17f3cSagc 		alias[0] = 0;
19775a17f3cSagc 
19875a17f3cSagc 	isns_free_trans(t);
19975a17f3cSagc 
20075a17f3cSagc 	if (ISNS_INVALID_TRANS ==
20175a17f3cSagc 		(t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS))) {
202*6fea88c2Smlelstv 		DEB(10,("get_targets iscsi_new_trans failed"));
20375a17f3cSagc 		return ISCSID_STATUS_NO_RESOURCES;
20475a17f3cSagc 	}
20575a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
20675a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
20775a17f3cSagc 
20875a17f3cSagc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
20975a17f3cSagc 
21075a17f3cSagc 	isns_add_tlv(t, isnst_PGiSCSIName, 0, NULL);	/* 48: portal name */
21175a17f3cSagc 	isns_add_tlv(t, isnst_PGPortIPAddr, 0, NULL);	/* 49: portal IP */
21275a17f3cSagc 	isns_add_tlv(t, isnst_PGPortIPPort, 0, NULL);	/* 50: portal port */
21375a17f3cSagc 	isns_add_tlv(t, isnst_PGTag, 0, NULL);	/* 51: group tag */
21475a17f3cSagc 
21575a17f3cSagc 	retval = isns_send_trans(t, &tout, &status);
216*6fea88c2Smlelstv 	DEB(9, ("isns_send_trans called, returns %d, status %d", retval, status));
21775a17f3cSagc 	if (retval) {
218*6fea88c2Smlelstv 		DEB(10,("iSNS Attribute Query failed, rc = %d", retval));
21975a17f3cSagc 		isns_free_trans(t);
22075a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
22175a17f3cSagc 	}
22275a17f3cSagc 	/* First is target name (the one we put in), ignore */
22375a17f3cSagc 	if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
224*6fea88c2Smlelstv 		DEB(10,("iSNS Attribute Query returned nothing"));
22575a17f3cSagc 		isns_free_trans(t);
22675a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
22775a17f3cSagc 	}
22875a17f3cSagc 	if (tag != isnst_iSCSIName) {
229*6fea88c2Smlelstv 		DEB(10,("iSNS Query2 returned bad name (tag = %d, length = %d)",
23075a17f3cSagc 				tag, data_len));
23175a17f3cSagc 		isns_free_trans(t);
23275a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
23375a17f3cSagc 	}
23475a17f3cSagc 
23575a17f3cSagc 	isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
23675a17f3cSagc 	if (tag != isnst_Delimiter) {
237*6fea88c2Smlelstv 		DEB(10,("Attr Query2 Missing Delimiter (tag = %d, length = %d)",
23875a17f3cSagc 				tag, data_len));
23975a17f3cSagc 		isns_free_trans(t);
24075a17f3cSagc 		return ISCSID_STATUS_ISNS_SERVER_ERROR;
24175a17f3cSagc 	}
24275a17f3cSagc 
24375a17f3cSagc 	while (!isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
24475a17f3cSagc 		if (tag != isnst_PGiSCSIName || !data_len ||
24575a17f3cSagc 			data_len >= ISCSI_STRING_LENGTH) {
246*6fea88c2Smlelstv 			DEB(10,("iSNS Query2 returned no or invalid name (tag=%d, "
247*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
24875a17f3cSagc 			isns_free_trans(t);
24975a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
25075a17f3cSagc 		}
25175a17f3cSagc 		strlcpy(name, (char *) data_p, sizeof(name));
25275a17f3cSagc 
25375a17f3cSagc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
25475a17f3cSagc 		if (tag != isnst_PGPortIPAddr || data_len != 16) {
255*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned no or invalid address (tag=%d, "
256*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
25775a17f3cSagc 			isns_free_trans(t);
25875a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
25975a17f3cSagc 		}
26075a17f3cSagc 		xlate_ip(addr.address, sizeof(addr.address), (uint8_t *) data_p);
26175a17f3cSagc 
26275a17f3cSagc 		/* Now comes the port */
26375a17f3cSagc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
26475a17f3cSagc 		if (tag != isnst_PGPortIPPort || data_len != 4) {
265*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned no or invalid port (tag=%d, "
266*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
26775a17f3cSagc 			isns_free_trans(t);
26875a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
26975a17f3cSagc 		}
27075a17f3cSagc 		u32 = ntohl(*((uint32_t *) data_p));
27175a17f3cSagc 		if (u32 & 0xffff0000) {
272*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned invalid port (flags=%x, "
273*6fea88c2Smlelstv 					"should be 0)", u32 >> 16));
27475a17f3cSagc 			isns_free_trans(t);
27575a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
27675a17f3cSagc 		}
27775a17f3cSagc 		addr.port = (uint16_t) u32;
27875a17f3cSagc 
27975a17f3cSagc 		/* And each target must have a group tag */
28075a17f3cSagc 		isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
28175a17f3cSagc 		if (tag != isnst_PGTag || (data_len && data_len != 4)) {
282*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned no or invalid group tag (tag=%d, "
283*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
28475a17f3cSagc 			isns_free_trans(t);
28575a17f3cSagc 			return ISCSID_STATUS_ISNS_SERVER_ERROR;
28675a17f3cSagc 		}
28775a17f3cSagc 		if (data_len) {
28875a17f3cSagc 			u32 = ntohl(*((uint32_t *) data_p));
28975a17f3cSagc 			addr.group_tag = (uint16_t) u32;
29075a17f3cSagc 		} else
29175a17f3cSagc 			addr.group_tag = 0;
29275a17f3cSagc 
29375a17f3cSagc 		/* we have everything necessary to describe the target, add it. */
29475a17f3cSagc 
295*6fea88c2Smlelstv 		DEB(2, ("Adding <%s>, IP <%s>, Port %d, Tag %d",
29675a17f3cSagc 				name, addr.address, addr.port, addr.group_tag));
29775a17f3cSagc 
29875a17f3cSagc 		if ((targ = add_discovered_target((unsigned char *)name, &addr, PORTAL_TYPE_ISNS,
29975a17f3cSagc 				isns->entry.sid.id)) == NULL) {
30075a17f3cSagc 			isns_free_trans(t);
30175a17f3cSagc 			return ISCSID_STATUS_NO_RESOURCES;
30275a17f3cSagc 		}
30375a17f3cSagc 
30475a17f3cSagc 		if (alias[0]) {
30575a17f3cSagc 			strlcpy((char *)targ->TargetAlias, alias,
30675a17f3cSagc 				sizeof(targ->TargetAlias));
30775a17f3cSagc 		}
30875a17f3cSagc 	}
30975a17f3cSagc 	isns_free_trans(t);
31075a17f3cSagc 
31175a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
31275a17f3cSagc }
31375a17f3cSagc 
31475a17f3cSagc 
31575a17f3cSagc /*
31675a17f3cSagc  * deregister_isns_server
31775a17f3cSagc  *  Support routine to deregister the initiator from the iSNS server
31875a17f3cSagc  *
31975a17f3cSagc  * Parameters:  The server descriptor
32075a17f3cSagc  *
32175a17f3cSagc  * Returns:     status
32275a17f3cSagc  */
32375a17f3cSagc 
32475a17f3cSagc static uint32_t
deregister_isns_server(isns_t * isns)32575a17f3cSagc deregister_isns_server(isns_t * isns)
32675a17f3cSagc {
32775a17f3cSagc 	int retval;
32875a17f3cSagc 	ISNS_TRANS t;
32975a17f3cSagc 	struct timespec tout = { 5, 0 };
33075a17f3cSagc 	uint32_t status;
33175a17f3cSagc 
33275a17f3cSagc 	/*
33375a17f3cSagc 	 * Create transaction for deregistering with iSNS server
33475a17f3cSagc 	 */
33575a17f3cSagc 
33675a17f3cSagc 	if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevDereg,
33775a17f3cSagc 												  MY_FLAGS))) {
338*6fea88c2Smlelstv 		DEB(10,("dereg_isns_server iscsi_new_trans failed"));
33975a17f3cSagc 		return ISCSID_STATUS_NO_RESOURCES;
34075a17f3cSagc 	}
34175a17f3cSagc 
34275a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
34375a17f3cSagc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
34475a17f3cSagc 	isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
345f7720048Schristos 	isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
34675a17f3cSagc 				 isns->reg_ip_addr);
347f7720048Schristos 	isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
34875a17f3cSagc 				 &isns->reg_ip_port);
34975a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
35075a17f3cSagc 
35175a17f3cSagc 	retval = isns_send_trans(t, &tout, &status);
352*6fea88c2Smlelstv 	DEB(9, ("DevAttrReg request returns %d, status %d", retval, status));
35375a17f3cSagc 
35475a17f3cSagc 	isns_free_trans(t);
35575a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
35675a17f3cSagc }
35775a17f3cSagc 
35875a17f3cSagc /*
35975a17f3cSagc  * register_isns_server
36075a17f3cSagc  *
36175a17f3cSagc  * Parameters:  The server descriptor
36275a17f3cSagc  *
36375a17f3cSagc  * Returns:     status
36475a17f3cSagc  */
36575a17f3cSagc 
36675a17f3cSagc 
36775a17f3cSagc static uint32_t
register_isns_server(isns_t * isns)36875a17f3cSagc register_isns_server(isns_t * isns)
36975a17f3cSagc {
37075a17f3cSagc 	int retval;
37175a17f3cSagc 	ISNS_TRANS t;
37275a17f3cSagc 	uint32_t u32;
37375a17f3cSagc 	struct timespec tout = { 5, 0 };
37475a17f3cSagc 	uint32_t status;
37575a17f3cSagc 
37675a17f3cSagc 	if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevAttrReg,
37775a17f3cSagc 												  MY_FLAGS))) {
378*6fea88c2Smlelstv 		DEB(10,("iscsi_new_trans failed"));
37975a17f3cSagc 		return ISCSID_STATUS_NO_RESOURCES;
38075a17f3cSagc 	}
38175a17f3cSagc 
38275a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);	/*tag=32 */
38375a17f3cSagc 	isns_add_tlv(t, isnst_Delimiter, 0, NULL);
38475a17f3cSagc 	isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
38575a17f3cSagc 	u32 = htonl(2);
386f7720048Schristos 	isns_add_tlv(t, isnst_EntProtocol, (uint32_t)sizeof(u32), &u32);
387f7720048Schristos 	isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
38875a17f3cSagc 				 isns->reg_ip_addr);
389f7720048Schristos 	isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
39075a17f3cSagc 				 &isns->reg_ip_port);
39175a17f3cSagc 	isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);	/*tag=32 */
39275a17f3cSagc 	u32 = htonl(2);
393f7720048Schristos 	isns_add_tlv(t, isnst_iSCSINodeType, (uint32_t)sizeof(u32), &u32);
39475a17f3cSagc 		/*tag=33 (node type = intiator) */
39575a17f3cSagc 
39675a17f3cSagc 	retval = isns_send_trans(t, &tout, &status);
397*6fea88c2Smlelstv 	DEB(9, ("DevAttrReg request returns %d, status %d", retval, status));
39875a17f3cSagc 	isns_free_trans(t);
39975a17f3cSagc 
40075a17f3cSagc 	if (retval || status)
40175a17f3cSagc 		return ISCSID_STATUS_ISNS_ERROR;
40275a17f3cSagc 
40375a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
40475a17f3cSagc }
40575a17f3cSagc 
40675a17f3cSagc 
40775a17f3cSagc /*
40875a17f3cSagc  * get_registration_info
40975a17f3cSagc  *
41075a17f3cSagc  * Parameters:  The server descriptor
41175a17f3cSagc  *
41275a17f3cSagc  * Returns:     status
41375a17f3cSagc  */
41475a17f3cSagc 
41575a17f3cSagc 
41675a17f3cSagc static uint32_t
get_registration_info(isns_t * isns)41775a17f3cSagc get_registration_info(isns_t * isns)
41875a17f3cSagc {
41975a17f3cSagc 	struct sockaddr_storage sa;
42075a17f3cSagc 	unsigned n;
42175a17f3cSagc 
42275a17f3cSagc 	strlcpy((char *)isns->reg_iscsi_name, (char *)node_name.InitiatorName,
42375a17f3cSagc 			sizeof(isns->reg_iscsi_name));
42475a17f3cSagc 	strlcpy((char *)isns->reg_entity_id, (char *)node_name.InitiatorAlias,
42575a17f3cSagc 			sizeof(isns->reg_entity_id));
42675a17f3cSagc 
42775a17f3cSagc 	/*Get our source IP and port numbers */
42875a17f3cSagc 	n = sizeof(sa);
429f7720048Schristos 	if (getsockname(isns->sock, (struct sockaddr *)(void *)&sa, &n)) {
430*6fea88c2Smlelstv 		DEB(10,("Getsockname returned error %d", errno));
43175a17f3cSagc 		return ISCSID_STATUS_GENERAL_ERROR;
43275a17f3cSagc 	}
43375a17f3cSagc 	switch (sa.ss_family) {
43475a17f3cSagc 	case AF_INET:
43575a17f3cSagc 		{
436f7720048Schristos 			struct sockaddr_in *si =
437f7720048Schristos 			    (struct sockaddr_in *)(void *)&sa;
438f7720048Schristos 			uint32_t *u32 = (uint32_t *)(void *)isns->reg_ip_addr;
43975a17f3cSagc 
44075a17f3cSagc 			u32[0] = u32[1] = 0;
44175a17f3cSagc 			u32[2] = htonl(0xffff);
44275a17f3cSagc 			u32[3] = htonl(si->sin_addr.s_addr);
44375a17f3cSagc 			isns->reg_ip_port = htons(si->sin_port);
44475a17f3cSagc 		}
44575a17f3cSagc 		break;
44675a17f3cSagc 
44775a17f3cSagc 	case AF_INET6:
44875a17f3cSagc 		{
449f7720048Schristos 			struct sockaddr_in6 *si =
450f7720048Schristos 			    (struct sockaddr_in6 *)(void *) &sa;
45175a17f3cSagc 
45275a17f3cSagc 			memcpy(isns->reg_ip_addr, &si->sin6_addr,
45375a17f3cSagc 					sizeof(isns->reg_ip_addr));
45475a17f3cSagc 			isns->reg_ip_port = htons(si->sin6_port);
45575a17f3cSagc 		}
45675a17f3cSagc 		break;
45775a17f3cSagc 
45875a17f3cSagc 	default:
459*6fea88c2Smlelstv 		DEB(10,("Getsockname returned unknown address family: %d",
46075a17f3cSagc 				sa.ss_family));
46175a17f3cSagc 		return ISCSID_STATUS_GENERAL_ERROR;
46275a17f3cSagc 	}
46375a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
46475a17f3cSagc }
46575a17f3cSagc 
46675a17f3cSagc 
46775a17f3cSagc /*
46875a17f3cSagc  * iscsi_isns_serverconn - given a set of server address, try connecting
46975a17f3cSagc  *
47075a17f3cSagc  * Parameters:  The descriptor for the iSNS server to query
47175a17f3cSagc  *
47275a17f3cSagc  * Returns:     status
47375a17f3cSagc  */
47475a17f3cSagc 
47575a17f3cSagc static uint32_t
iscsi_isns_serverconn(isns_t * isns)47675a17f3cSagc iscsi_isns_serverconn(isns_t * isns)
47775a17f3cSagc {
47875a17f3cSagc 	int sock = -1;
47975a17f3cSagc 	char port[16];
48075a17f3cSagc 	struct addrinfo hints;
48175a17f3cSagc 	struct addrinfo *ai, *addr;
48275a17f3cSagc 	int retval;
48375a17f3cSagc 
48475a17f3cSagc 	/*
48575a17f3cSagc 	 * Initialize the iSNS library if it needs it
48675a17f3cSagc 	 */
48775a17f3cSagc 
48875a17f3cSagc 	if (isns_handle == ISNS_INVALID_HANDLE) {
48975a17f3cSagc 		if ((retval = isns_init(&isns_handle, 0)) != 0) {
49075a17f3cSagc 			/*Couldn't initialize the iSNS library */
491*6fea88c2Smlelstv 			DEB(10,("isns_init failed with code %d", retval));
49275a17f3cSagc 			isns_handle = ISNS_INVALID_HANDLE;
49375a17f3cSagc 			return ISCSID_STATUS_GENERAL_ERROR;
49475a17f3cSagc 		}
49575a17f3cSagc 	}
49675a17f3cSagc 
49775a17f3cSagc 	/*
49875a17f3cSagc 	 * Find the server address from the iSNS server list entry,
49975a17f3cSagc 	 * and try to connect to the iSNS server
50075a17f3cSagc 	 */
50175a17f3cSagc 
50275a17f3cSagc 	snprintf(port, sizeof(port), "%d", (isns->port) ? isns->port : ISCSI_DEFAULT_ISNS_PORT);
50375a17f3cSagc 	memset(&hints, 0, sizeof(hints));
50475a17f3cSagc 	hints.ai_family = PF_UNSPEC;
50575a17f3cSagc 	hints.ai_socktype = SOCK_STREAM;
50675a17f3cSagc 	hints.ai_protocol = IPPROTO_TCP;
50775a17f3cSagc 
50875a17f3cSagc 	retval = getaddrinfo((char *)isns->address, port, &hints, &ai);
50975a17f3cSagc 	if (retval) {
510*6fea88c2Smlelstv 		DEB(10,("getaddrinfo failed with code %d (%s)",
51175a17f3cSagc 				retval, gai_strerror(retval)));
51275a17f3cSagc 		return ISCSID_STATUS_GENERAL_ERROR;
51375a17f3cSagc 	}
51475a17f3cSagc 
51575a17f3cSagc 	for (addr = ai; addr != NULL; addr = addr->ai_next) {
516f7720048Schristos 		sock = socket(addr->ai_family, addr->ai_socktype,
517f7720048Schristos 		    addr->ai_protocol);
51875a17f3cSagc 
519f7720048Schristos 		if (sock == -1) {
520*6fea88c2Smlelstv 			DEB(10,("%s: socket call FAILED!", __func__));
52175a17f3cSagc 			freeaddrinfo(ai);
522f7720048Schristos 			return (uint32_t)-1;
52375a17f3cSagc 		}
52475a17f3cSagc 
525af909e15Smlelstv 		if (connect(sock, addr->ai_addr, addr->ai_addrlen) != -1)
52675a17f3cSagc 			break;
52775a17f3cSagc 
528*6fea88c2Smlelstv 		DEB(1, ("%s: connect call FAILED!", __func__));
52975a17f3cSagc 		close(sock);
53075a17f3cSagc 		sock = -1;
53175a17f3cSagc 	}
53275a17f3cSagc 
53375a17f3cSagc 	if (addr == NULL) {
534*6fea88c2Smlelstv 		DEB(10,("%s: couldn't connect!", __func__));
53575a17f3cSagc 		freeaddrinfo(ai);
53675a17f3cSagc 		return ISCSID_STATUS_GENERAL_ERROR;
53775a17f3cSagc 	}
53875a17f3cSagc 
53975a17f3cSagc 	if (isns_add_servercon(isns_handle, sock, addr)) {
540*6fea88c2Smlelstv 		DEB(10,("%s: FAILED!", __func__));
54175a17f3cSagc 		close(sock);
54275a17f3cSagc 		freeaddrinfo(ai);
54375a17f3cSagc 		return ISCSID_STATUS_GENERAL_ERROR;
54475a17f3cSagc 	}
54575a17f3cSagc 
54675a17f3cSagc 	freeaddrinfo(ai);
54775a17f3cSagc 	isns->sock = sock;
54875a17f3cSagc 
54975a17f3cSagc 	if ((retval = get_registration_info(isns)) != 0) {
55075a17f3cSagc 		return retval;
55175a17f3cSagc 	}
55275a17f3cSagc 
55375a17f3cSagc 	deregister_isns_server(isns);
55475a17f3cSagc 
55575a17f3cSagc 	return register_isns_server(isns);
55675a17f3cSagc }
55775a17f3cSagc 
55875a17f3cSagc 
55975a17f3cSagc /*
56075a17f3cSagc  * update_isns_server_info
56175a17f3cSagc  *  Support routine to query the specified iSNS server for all targets
56275a17f3cSagc  *  Called from add_isns_server and refresh_isns_server
56375a17f3cSagc  *
56475a17f3cSagc  * Parameters:  The descriptor for the iSNS server to query
56575a17f3cSagc  *
56675a17f3cSagc  * Returns:     status
56775a17f3cSagc  */
56875a17f3cSagc 
56975a17f3cSagc 
57075a17f3cSagc static uint32_t
update_isns_server_info(isns_t * isns)57175a17f3cSagc update_isns_server_info(isns_t * isns)
57275a17f3cSagc {
57375a17f3cSagc 	int retval;
57475a17f3cSagc 	ISNS_TRANS t;
57575a17f3cSagc 	uint32_t tag;
576f7720048Schristos 	uint32_t data_len;
57775a17f3cSagc 	void *data_p;
57875a17f3cSagc 	uint32_t u32;
57975a17f3cSagc 	struct timespec tout = { 5, 0 };
58075a17f3cSagc 	uint32_t status;
58175a17f3cSagc 	uint8_t TargetName[ISCSI_STRING_LENGTH];
58275a17f3cSagc 
58375a17f3cSagc 
584*6fea88c2Smlelstv 	DEB(9, ("update_isns_server_info for iSNS %s", isns->address));
58575a17f3cSagc 
58675a17f3cSagc 	if (isns->sock < 0) {
58775a17f3cSagc 		if ((status = iscsi_isns_serverconn(isns)) != 0) {
58875a17f3cSagc 			/*We couldn't connect to the iSNS server */
589*6fea88c2Smlelstv 			DEB(9, ("update_isns_server_info iscsi_isns_serverconn failed"));
59075a17f3cSagc 			return status;
59175a17f3cSagc 		}
59275a17f3cSagc 	}
59375a17f3cSagc 
59475a17f3cSagc 	for (TargetName[0] = 0;;) {
59575a17f3cSagc 		if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle,
59675a17f3cSagc 												isnsp_DevGetNext, MY_FLAGS))) {
597*6fea88c2Smlelstv 			DEB(10,("update_isns_server_info iscsi_new_trans failed"));
59875a17f3cSagc 			return ISCSID_STATUS_NO_RESOURCES;
59975a17f3cSagc 		}
60075a17f3cSagc 
60175a17f3cSagc 		isns_add_string(t, isnst_iSCSIName, (char *)node_name.InitiatorName);
60275a17f3cSagc 
60375a17f3cSagc 		if (TargetName[0])
60475a17f3cSagc 			isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
60575a17f3cSagc 		else
60675a17f3cSagc 			isns_add_tlv(t, isnst_iSCSIName, 0, NULL);
60775a17f3cSagc 
60875a17f3cSagc 		isns_add_tlv(t, isnst_Delimiter, 0, NULL);
60975a17f3cSagc 		isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL);
61075a17f3cSagc 
61175a17f3cSagc 		if ((retval = isns_send_trans(t, &tout, &status)) != 0) {
612*6fea88c2Smlelstv 			DEB(10,("isns_send_trans returns rc %d, status %d",
61375a17f3cSagc 					retval, status));
61475a17f3cSagc 			isns_free_trans(t);
61575a17f3cSagc 			break;
61675a17f3cSagc 		}
61775a17f3cSagc 		if (status) {
618*6fea88c2Smlelstv 			DEB(9, ("DevGetNext Status = %d", status));
61975a17f3cSagc 			break;
62075a17f3cSagc 		}
62175a17f3cSagc 
62275a17f3cSagc 		if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
623*6fea88c2Smlelstv 			DEB(10,("No TLV in DevGetNext response!"));
62475a17f3cSagc 			isns_free_trans(t);
62575a17f3cSagc 			break;
62675a17f3cSagc 		}
62775a17f3cSagc 		/* We need the name, or there's nothing left to do */
62875a17f3cSagc 
62975a17f3cSagc 		if (tag != isnst_iSCSIName || !data_len ||
63075a17f3cSagc 			data_len >= ISCSI_STRING_LENGTH) {
631*6fea88c2Smlelstv 			DEB(10,("iSNS GetNextDev returned no or invalid name (tag=%d, "
632*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
63375a17f3cSagc 			isns_free_trans(t);
63475a17f3cSagc 			break;
63575a17f3cSagc 		}
63675a17f3cSagc 		strlcpy((char *)TargetName, (char *) data_p, sizeof(TargetName));
63775a17f3cSagc 
63875a17f3cSagc 		/* We must get at least the node type, and it must be a target */
63975a17f3cSagc 		if (isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
640*6fea88c2Smlelstv 			DEB(10,("iSNS GetDevNext did not return node type"));
64175a17f3cSagc 			isns_free_trans(t);
64275a17f3cSagc 			break;
64375a17f3cSagc 		}
64475a17f3cSagc 		if (tag == isnst_Delimiter && isns_get_tlv(t, ISNS_TLV_NEXT, &tag,
64575a17f3cSagc 													&data_len, &data_p)) {
646*6fea88c2Smlelstv 			DEB(10,("iSNS GetDevNext did not return node type (past delim)"));
64775a17f3cSagc 			isns_free_trans(t);
64875a17f3cSagc 			break;
64975a17f3cSagc 		}
65075a17f3cSagc 		if (tag != isnst_iSCSINodeType || data_len != 4) {
651*6fea88c2Smlelstv 			DEB(10,("iSNS Query returned no or invalid node type (tag=%d, "
652*6fea88c2Smlelstv 					"length=%d)", tag, data_len));
65375a17f3cSagc 			isns_free_trans(t);
65475a17f3cSagc 			break;
65575a17f3cSagc 		}
65675a17f3cSagc 		u32 = ntohl(*((uint32_t *) data_p));
65775a17f3cSagc 		isns_free_trans(t);
65875a17f3cSagc 
65975a17f3cSagc 		if (u32 & 1)
66075a17f3cSagc 			get_isns_target_info(isns, TargetName);
66175a17f3cSagc 	}
66275a17f3cSagc 
663*6fea88c2Smlelstv 	DEB(9, ("update_isns_server_info returning SUCCESS!"));
66475a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
66575a17f3cSagc }
66675a17f3cSagc 
66775a17f3cSagc 
66875a17f3cSagc /**********************************************************************
66975a17f3cSagc **********************************************************************/
67075a17f3cSagc 
67175a17f3cSagc /*
67275a17f3cSagc  * create_isns:
67375a17f3cSagc  *    Create an isns structure and initialize it.
67475a17f3cSagc  *
67575a17f3cSagc  *    Parameter:
67675a17f3cSagc  *          name        The iSNS server name
67775a17f3cSagc  *
67875a17f3cSagc  *    Returns:    Pointer to isns structure, NULL if allocation failed.
67975a17f3cSagc  */
68075a17f3cSagc 
68138a27f5aSagc static isns_t *
create_isns(iscsid_add_isns_server_req_t * req)68275a17f3cSagc create_isns(iscsid_add_isns_server_req_t * req)
68375a17f3cSagc {
68475a17f3cSagc 	isns_t *isns;
68575a17f3cSagc 
686*6fea88c2Smlelstv 	DEB(9, ("Create iSNS %s", req->address));
68775a17f3cSagc 
68875a17f3cSagc 	if ((isns = calloc(1, sizeof(*isns))) == NULL)
68975a17f3cSagc 		return NULL;
69075a17f3cSagc 
69175a17f3cSagc 	for (isns_id++; !isns_id || find_isns_id(isns_id) != NULL;)
69275a17f3cSagc 		isns_id++;
69375a17f3cSagc 
69475a17f3cSagc 	isns->entry.sid.id = isns_id;
69575a17f3cSagc 	strlcpy((char *)isns->entry.sid.name, (char *)req->name, sizeof(isns->entry.sid.name));
69675a17f3cSagc 	strlcpy((char *)isns->address, (char *)req->address, sizeof(isns->address));
69775a17f3cSagc 	isns->port = req->port;
69875a17f3cSagc 	isns->sock = -1;
69975a17f3cSagc 
70075a17f3cSagc 	return isns;
70175a17f3cSagc }
70275a17f3cSagc 
70375a17f3cSagc 
70475a17f3cSagc /*
70575a17f3cSagc  * add_isns_server
70675a17f3cSagc  *    Adds an iSNS server to the server list.
70775a17f3cSagc  *    This command will add the address of an iSNS server to the list
70875a17f3cSagc  *      of iSNS servers that the discovery daemon queries to discover targets.
70975a17f3cSagc  *      The daemon will then register itself with the iSNS server,
71075a17f3cSagc  *      and query the iSNS server for the list of targets.
71175a17f3cSagc  *      The discovered targets will be added to the list of target portals.
71275a17f3cSagc  *      The response contains the ID of the iSNS server.
71375a17f3cSagc  *
71475a17f3cSagc  * Parameter:  The parameter contains the address of the server.
71575a17f3cSagc  *
71675a17f3cSagc  * Returns:    Nothing
71775a17f3cSagc  *             The response parameter is an iscsid_add_isns_server_rsp_t
71875a17f3cSagc  *             containing:
71975a17f3cSagc  *                  server_id = Unique ID for the iSNS server
72075a17f3cSagc  */
72175a17f3cSagc 
72275a17f3cSagc void
add_isns_server(iscsid_add_isns_server_req_t * req,iscsid_response_t ** prsp,int * prsp_temp)72375a17f3cSagc add_isns_server(iscsid_add_isns_server_req_t * req, iscsid_response_t ** prsp,
72475a17f3cSagc 				int *prsp_temp)
72575a17f3cSagc {
72675a17f3cSagc 	iscsid_response_t *rsp = *prsp;
72775a17f3cSagc 	iscsid_add_isns_server_rsp_t *res;
72875a17f3cSagc 	isns_t *isns;
72975a17f3cSagc 
730*6fea88c2Smlelstv 	DEB(9, ("IN add_isns_server"));
73175a17f3cSagc 
73275a17f3cSagc 	/*
73375a17f3cSagc 	 * Make a response
73475a17f3cSagc 	 */
73575a17f3cSagc 
73675a17f3cSagc 	rsp = make_rsp(sizeof(iscsid_add_isns_server_rsp_t), prsp, prsp_temp);
73775a17f3cSagc 	if (rsp == NULL) {
738*6fea88c2Smlelstv 		DEB(9, ("OUT add_isns_server: make_rsp FAILED"));
73975a17f3cSagc 		return;
74075a17f3cSagc 	}
74175a17f3cSagc 
742f7720048Schristos 	res = (iscsid_add_isns_server_rsp_t *)(void *)rsp->parameter;
74375a17f3cSagc 
74475a17f3cSagc 	/*
74575a17f3cSagc 	 * First, allocate the isns server structure to put on the list
74675a17f3cSagc 	 */
74775a17f3cSagc 
74875a17f3cSagc 	isns = create_isns(req);
74975a17f3cSagc 	if (isns == NULL) {
75075a17f3cSagc 		rsp->status = ISCSID_STATUS_NO_RESOURCES;
751*6fea88c2Smlelstv 		DEB(9, ("OUT add_isns_server: create_isns FAILED!"));
75275a17f3cSagc 		return;
75375a17f3cSagc 	}
75475a17f3cSagc 
75575a17f3cSagc 	TAILQ_INSERT_TAIL(&list[ISNS_LIST].list, &isns->entry, link);
75675a17f3cSagc 	list[ISNS_LIST].num_entries++;
75775a17f3cSagc 	res->server_id = isns->entry.sid.id;
75875a17f3cSagc 
759*6fea88c2Smlelstv 	DEB(9, ("OUT add_isns_server: server_id = %d, name = %s",
76075a17f3cSagc 			isns->entry.sid.id, isns->address));
76175a17f3cSagc 
76275a17f3cSagc 	/*
76375a17f3cSagc 	 * Now try to connect to the iSNS server...
76475a17f3cSagc 	 */
76575a17f3cSagc 
76675a17f3cSagc 	update_isns_server_info(isns);
76775a17f3cSagc }
76875a17f3cSagc 
76975a17f3cSagc 
77075a17f3cSagc /*
77175a17f3cSagc  * get_isns_server
77275a17f3cSagc  *    Returns the address of the iSNS server with the specified ID
77375a17f3cSagc  *
77475a17f3cSagc  * Parameters:  The unique ID of the server
77575a17f3cSagc  *
77675a17f3cSagc  * Returns:     The status returned by the driver
77775a17f3cSagc  *              The response parameter contains the iSNS server address as a
77875a17f3cSagc  *              zero-terminated UTF-8 string
77975a17f3cSagc  */
78075a17f3cSagc 
78175a17f3cSagc void
get_isns_server(iscsid_sym_id_t * preq,iscsid_response_t ** prsp,int * prsp_temp)78275a17f3cSagc get_isns_server(iscsid_sym_id_t * preq, iscsid_response_t ** prsp,
78375a17f3cSagc 				int *prsp_temp)
78475a17f3cSagc {
78575a17f3cSagc 	iscsid_response_t *rsp = *prsp;
78675a17f3cSagc 	iscsid_get_isns_server_rsp_t *res;
78775a17f3cSagc 	isns_t *isns;
78875a17f3cSagc 
789*6fea88c2Smlelstv 	DEB(9, ("IN get_isns_server"));
79075a17f3cSagc 	isns = find_isns(preq);
79175a17f3cSagc 	if (isns == NULL) {
79275a17f3cSagc 		rsp->status = ISCSID_STATUS_INVALID_ISNS_ID;
793*6fea88c2Smlelstv 		DEB(9, ("OUT get_isns_server: find_isns FAILED!"));
79475a17f3cSagc 		return;
79575a17f3cSagc 	}
79675a17f3cSagc 
79775a17f3cSagc 	rsp = make_rsp(sizeof(iscsid_get_isns_server_rsp_t), prsp, prsp_temp);
79875a17f3cSagc 	if (rsp == NULL) {
799*6fea88c2Smlelstv 		DEB(9, ("OUT get_isns_server: make_rsp FAILED!"));
80075a17f3cSagc 		return;
80175a17f3cSagc 	}
802f7720048Schristos 	res = (iscsid_get_isns_server_rsp_t *)(void *)rsp->parameter;
80375a17f3cSagc 
804f7720048Schristos 	strlcpy((char *)res->address, (char *)isns->address,
805f7720048Schristos 	    sizeof(res->address));
80675a17f3cSagc 	res->port = isns->port;
80775a17f3cSagc 	res->server_id = isns->entry.sid;
808*6fea88c2Smlelstv 	DEB(9, ("OUT get_isns_server: id = %d, address = %s",
80975a17f3cSagc 			res->server_id.id, res->address));
81075a17f3cSagc }
81175a17f3cSagc 
81275a17f3cSagc 
81375a17f3cSagc /*
81475a17f3cSagc  * slp_find_isns_servers
81575a17f3cSagc  */
81675a17f3cSagc 
81775a17f3cSagc /* More Here Later... */
81875a17f3cSagc 
81975a17f3cSagc 
82075a17f3cSagc /*
82175a17f3cSagc  * refresh_isns_server
82275a17f3cSagc  *    Query the specified iSNS servers for the list of targets.
82375a17f3cSagc  *
82475a17f3cSagc  *    Parameters:
82575a17f3cSagc  *          id    Server ID
82675a17f3cSagc  *
82775a17f3cSagc  *    Returns:     Status
82875a17f3cSagc  */
82975a17f3cSagc 
83075a17f3cSagc uint32_t
refresh_isns_server(uint32_t id)83175a17f3cSagc refresh_isns_server(uint32_t id)
83275a17f3cSagc {
83375a17f3cSagc 	uint32_t rc;
83475a17f3cSagc 	isns_t *isns;
83575a17f3cSagc 	generic_entry_t *curr;
83675a17f3cSagc 	generic_entry_t *next;
83775a17f3cSagc 
83875a17f3cSagc 	isns = find_isns_id(id);
83975a17f3cSagc 	if (isns == NULL)
84075a17f3cSagc 		return ISCSID_STATUS_INVALID_ISNS_ID;
84175a17f3cSagc 
84275a17f3cSagc 	TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
843f7720048Schristos 		portal_t *p = (portal_t *)(void *)curr;
844f7720048Schristos 		if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
845f7720048Schristos 			p->portaltype = PORTAL_TYPE_REFRESHING;
84675a17f3cSagc 	}
84775a17f3cSagc 
84875a17f3cSagc 	rc = update_isns_server_info(isns);
84975a17f3cSagc 
85075a17f3cSagc 	/*
85175a17f3cSagc 	 * Go through our list of portals and look for ones
85275a17f3cSagc 	 * that are still marked for refreshing.
85375a17f3cSagc 	 * These are ones that are no longer there and should be removed.
85475a17f3cSagc 	 */
85575a17f3cSagc 
85675a17f3cSagc 	for (curr = TAILQ_FIRST(&list[PORTAL_LIST].list); curr != NULL;
85775a17f3cSagc 		 curr = next) {
858f7720048Schristos 		portal_t *p = (portal_t *)(void *)curr;
85975a17f3cSagc 		next = TAILQ_NEXT(curr, link);
860f7720048Schristos 		if (p->portaltype == PORTAL_TYPE_REFRESHING)
861f7720048Schristos 			delete_portal(p, TRUE);
86275a17f3cSagc 	}
86375a17f3cSagc 
86475a17f3cSagc 	return rc;
86575a17f3cSagc }
86675a17f3cSagc 
86775a17f3cSagc 
86875a17f3cSagc /*
86975a17f3cSagc  * remove_isns_server
87075a17f3cSagc  *    Removed an iSNS server.
87175a17f3cSagc  *    This does not remove the discovered targets from the list.
87275a17f3cSagc  *
87375a17f3cSagc  * Parameters:  The iscid_remove_isns_req_t structure containing:
87475a17f3cSagc  *                  server_id = unique ID of server to remove
87575a17f3cSagc  *
87675a17f3cSagc  * Returns:     The status returned.
87775a17f3cSagc  */
87875a17f3cSagc 
87975a17f3cSagc uint32_t
remove_isns_server(iscsid_sym_id_t * preq)88075a17f3cSagc remove_isns_server(iscsid_sym_id_t * preq)
88175a17f3cSagc {
88275a17f3cSagc 	generic_entry_t *curr;
88375a17f3cSagc 	isns_t *isns;
88475a17f3cSagc 	uint32_t id;
88575a17f3cSagc 
88675a17f3cSagc 	isns = find_isns(preq);
88775a17f3cSagc 	if (isns == NULL)
88875a17f3cSagc 		return ISCSID_STATUS_INVALID_ISNS_ID;
88975a17f3cSagc 
89075a17f3cSagc 	/*Deregister with the iSNS server. */
89175a17f3cSagc 	/*Ignore any errors during deregistration... */
89275a17f3cSagc 	if (isns->sock >= 0) {
89375a17f3cSagc 		deregister_isns_server(isns);
89475a17f3cSagc 		close(isns->sock);
89575a17f3cSagc 	}
89675a17f3cSagc 
89775a17f3cSagc 	TAILQ_REMOVE(&list[ISNS_LIST].list, &isns->entry, link);
89875a17f3cSagc 	list[ISNS_LIST].num_entries--;
89975a17f3cSagc 
90075a17f3cSagc 	id = isns->entry.sid.id;
90175a17f3cSagc 	free(isns);
90275a17f3cSagc 
90375a17f3cSagc 	TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
904f7720048Schristos 		portal_t *p = (portal_t *)(void *)curr;
905f7720048Schristos 		if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
906f7720048Schristos 			p->discoveryid = 0; /* mark deleted */
90775a17f3cSagc 	}
90875a17f3cSagc 
90975a17f3cSagc 	return ISCSID_STATUS_SUCCESS;
91075a17f3cSagc }
91175a17f3cSagc 
91275a17f3cSagc 
91375a17f3cSagc /*
91475a17f3cSagc    Deregister all isns servers on daemon termination
91575a17f3cSagc */
91675a17f3cSagc 
91775a17f3cSagc void
dereg_all_isns_servers(void)91875a17f3cSagc dereg_all_isns_servers(void)
91975a17f3cSagc {
92075a17f3cSagc 	generic_list_t *plist;
92175a17f3cSagc 	generic_entry_t *curr;
92275a17f3cSagc 
92375a17f3cSagc 	plist = &list[ISNS_LIST].list;
92475a17f3cSagc 	TAILQ_FOREACH(curr, plist, link)
925f7720048Schristos 		deregister_isns_server((isns_t *)(void *)curr);
92675a17f3cSagc }
92775a17f3cSagc 
92875a17f3cSagc #endif
92975a17f3cSagc 
930