1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22904e51f6SJack Meng  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23*7284664aSJoshua M. Clulow  * Copyright 2019 Joshua M. Clulow <josh@sysmgr.org>
24fcf3ce44SJohn Forte  */
25fcf3ce44SJohn Forte 
26fcf3ce44SJohn Forte /*
27fcf3ce44SJohn Forte  * ISCSID --
28fcf3ce44SJohn Forte  *
29fcf3ce44SJohn Forte  * Discovery of targets and access to the persistent storage starts here.
30fcf3ce44SJohn Forte  */
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte #include <sys/thread.h>
33fcf3ce44SJohn Forte #include <sys/types.h>
34fcf3ce44SJohn Forte #include <sys/proc.h>		/* declares:    p0 */
35fcf3ce44SJohn Forte #include <sys/cmn_err.h>
36fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_if.h>
37fcf3ce44SJohn Forte #include <netinet/in.h>
38fcf3ce44SJohn Forte #include "iscsi_targetparam.h"
39fcf3ce44SJohn Forte #include "isns_client.h"
40fcf3ce44SJohn Forte #include "isns_protocol.h"
41fcf3ce44SJohn Forte #include "persistent.h"
42fcf3ce44SJohn Forte #include "iscsi.h"
43fcf3ce44SJohn Forte #include <sys/ethernet.h>
446cefaae1SJack Meng #include <sys/bootprops.h>
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte /*
47fcf3ce44SJohn Forte  * local function prototypes
48fcf3ce44SJohn Forte  */
49fcf3ce44SJohn Forte static boolean_t iscsid_init_config(iscsi_hba_t *ihp);
50fcf3ce44SJohn Forte static boolean_t iscsid_init_targets(iscsi_hba_t *ihp);
51fcf3ce44SJohn Forte static void iscsid_thread_static(iscsi_thread_t *thread, void *p);
52fcf3ce44SJohn Forte static void iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p);
53fcf3ce44SJohn Forte static void iscsid_thread_isns(iscsi_thread_t *thread, void *p);
54fcf3ce44SJohn Forte static void iscsid_thread_slp(iscsi_thread_t *thread, void *p);
556cefaae1SJack Meng static void iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p);
56fcf3ce44SJohn Forte static void iscsid_threads_create(iscsi_hba_t *ihp);
57fcf3ce44SJohn Forte static void iscsid_threads_destroy(void);
58fcf3ce44SJohn Forte static int iscsid_copyto_param_set(uint32_t param_id,
59fcf3ce44SJohn Forte     iscsi_login_params_t *params, iscsi_param_set_t *ipsp);
60fcf3ce44SJohn Forte static void iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
61fcf3ce44SJohn Forte     isns_portal_group_list_t *pg_list);
62fcf3ce44SJohn Forte static void iscsid_remove_target_param(char *name);
63fcf3ce44SJohn Forte static boolean_t iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
64fcf3ce44SJohn Forte     struct sockaddr *addr_dsc, char *target_name, int tpgt,
65fcf3ce44SJohn Forte     struct sockaddr *addr_tgt);
66fcf3ce44SJohn Forte static void iscsi_discovery_event(iscsi_hba_t *ihp,
67fcf3ce44SJohn Forte     iSCSIDiscoveryMethod_t m, boolean_t start);
686cefaae1SJack Meng static boolean_t iscsid_boot_init_config(iscsi_hba_t *ihp);
696cefaae1SJack Meng static iscsi_sess_t *iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid);
706cefaae1SJack Meng static boolean_t iscsid_make_entry(ib_boot_prop_t *boot_prop_entry,
716cefaae1SJack Meng     entry_t *entry);
72f53e1f19SJack Meng static boolean_t iscsid_check_active_boot_conn(iscsi_hba_t *ihp);
736cefaae1SJack Meng 
746cefaae1SJack Meng extern int modrootloaded;
756cefaae1SJack Meng int iscsi_configroot_retry = 20;
766cefaae1SJack Meng static boolean_t iscsi_configroot_printed = FALSE;
7730e7468fSPeter Dunlap static int iscsi_net_up = 0;
786cefaae1SJack Meng extern ib_boot_prop_t   *iscsiboot_prop;
79fcf3ce44SJohn Forte 
80f53e1f19SJack Meng #define	ISCSI_CONFIGROOT_DELAY	1
81f53e1f19SJack Meng 
82fcf3ce44SJohn Forte /*
83fcf3ce44SJohn Forte  * iSCSI target discovery thread table
84fcf3ce44SJohn Forte  */
85fcf3ce44SJohn Forte typedef struct iscsid_thr_table {
86fcf3ce44SJohn Forte 	void			(*func_start)(iscsi_thread_t *, void *);
87fcf3ce44SJohn Forte 	iscsi_thread_t		*thr_id;
88fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t	method;
89fcf3ce44SJohn Forte 	char			*name;
90fcf3ce44SJohn Forte } iscsid_thr_table;
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte static iscsid_thr_table iscsid_thr[] = {
93fcf3ce44SJohn Forte 	{ iscsid_thread_static, NULL,
94fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodStatic,
95fcf3ce44SJohn Forte 	    "Static" },
96fcf3ce44SJohn Forte 	{ iscsid_thread_sendtgts, NULL,
97fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodSendTargets,
98fcf3ce44SJohn Forte 	    "SendTarget" },
99fcf3ce44SJohn Forte 	{ iscsid_thread_slp, NULL,
100fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodSLP,
101fcf3ce44SJohn Forte 	    "SLP" },
102fcf3ce44SJohn Forte 	{ iscsid_thread_isns, NULL,
103fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodISNS,
104fcf3ce44SJohn Forte 	    "iSNS" },
105fcf3ce44SJohn Forte 	{ NULL, NULL,
106fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodUnknown,
107fcf3ce44SJohn Forte 	    NULL }
108fcf3ce44SJohn Forte };
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte /*
111fcf3ce44SJohn Forte  * discovery method event table
112fcf3ce44SJohn Forte  */
113fcf3ce44SJohn Forte iSCSIDiscoveryMethod_t	for_failure[] = {
114fcf3ce44SJohn Forte 	iSCSIDiscoveryMethodStatic,
115fcf3ce44SJohn Forte 	iSCSIDiscoveryMethodSLP,
116fcf3ce44SJohn Forte 	iSCSIDiscoveryMethodISNS,
117fcf3ce44SJohn Forte 	iSCSIDiscoveryMethodSendTargets,
118fcf3ce44SJohn Forte 	iSCSIDiscoveryMethodUnknown /* terminating value */
119fcf3ce44SJohn Forte };
120fcf3ce44SJohn Forte 
1216cefaae1SJack Meng /*
1226cefaae1SJack Meng  * The following private tunable, set in /etc/system, e.g.,
1236cefaae1SJack Meng  *      set iscsi:iscsi_boot_max_delay = 360
1246cefaae1SJack Meng  * , provides with customer a max wait time in
1256cefaae1SJack Meng  * seconds to wait for boot lun online during iscsi boot.
1266cefaae1SJack Meng  * Defaults to 180s.
1276cefaae1SJack Meng  */
1286cefaae1SJack Meng int iscsi_boot_max_delay = ISCSI_BOOT_DEFAULT_MAX_DELAY;
1296cefaae1SJack Meng 
130fcf3ce44SJohn Forte /*
131fcf3ce44SJohn Forte  * discovery configuration semaphore
132fcf3ce44SJohn Forte  */
133fcf3ce44SJohn Forte ksema_t iscsid_config_semaphore;
134fcf3ce44SJohn Forte 
1356cefaae1SJack Meng static iscsi_thread_t	*iscsi_boot_wd_handle = NULL;
1366cefaae1SJack Meng 
137fcf3ce44SJohn Forte #define	CHECK_METHOD(v) ((dm & v) ? B_TRUE : B_FALSE)
138fcf3ce44SJohn Forte 
1396cefaae1SJack Meng /*
1406cefaae1SJack Meng  * Check if IP is valid
1416cefaae1SJack Meng  */
1426cefaae1SJack Meng static boolean_t
iscsid_ip_check(char * ip)1436cefaae1SJack Meng iscsid_ip_check(char *ip)
1446cefaae1SJack Meng {
1456cefaae1SJack Meng 	int	i	= 0;
1466cefaae1SJack Meng 
1476cefaae1SJack Meng 	if (!ip)
1486cefaae1SJack Meng 		return (B_FALSE);
1496cefaae1SJack Meng 	for (; (ip[i] == 0) && (i < IB_IP_BUFLEN); i++) {}
1506cefaae1SJack Meng 	if (i == IB_IP_BUFLEN) {
1516cefaae1SJack Meng 		/* invalid IP address */
1526cefaae1SJack Meng 		return (B_FALSE);
1536cefaae1SJack Meng 	}
1546cefaae1SJack Meng 	return (B_TRUE);
1556cefaae1SJack Meng }
1566cefaae1SJack Meng 
1576cefaae1SJack Meng /*
1586cefaae1SJack Meng  * Make an entry for the boot target.
1596cefaae1SJack Meng  * return B_TRUE upon success
1606cefaae1SJack Meng  *        B_FALSE if fail
1616cefaae1SJack Meng  */
1626cefaae1SJack Meng static boolean_t
iscsid_make_entry(ib_boot_prop_t * boot_prop_entry,entry_t * entry)1636cefaae1SJack Meng iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, entry_t *entry)
1646cefaae1SJack Meng {
1656cefaae1SJack Meng 	if (entry == NULL || boot_prop_entry == NULL) {
1666cefaae1SJack Meng 		return (B_FALSE);
1676cefaae1SJack Meng 	}
1686cefaae1SJack Meng 
1696cefaae1SJack Meng 	if (!iscsid_ip_check(
1706cefaae1SJack Meng 	    (char *)&boot_prop_entry->boot_tgt.tgt_ip_u))
1716cefaae1SJack Meng 		return (B_FALSE);
1726cefaae1SJack Meng 
1736cefaae1SJack Meng 	if (boot_prop_entry->boot_tgt.sin_family != AF_INET &&
1746cefaae1SJack Meng 	    boot_prop_entry->boot_tgt.sin_family != AF_INET6)
1756cefaae1SJack Meng 		return (B_FALSE);
1766cefaae1SJack Meng 
1776cefaae1SJack Meng 	entry->e_vers = ISCSI_INTERFACE_VERSION;
1786cefaae1SJack Meng 
1796cefaae1SJack Meng 	mutex_enter(&iscsi_oid_mutex);
1806cefaae1SJack Meng 	entry->e_oid = iscsi_oid++;
1816cefaae1SJack Meng 	mutex_exit(&iscsi_oid_mutex);
1826cefaae1SJack Meng 
1836cefaae1SJack Meng 	entry->e_tpgt = ISCSI_DEFAULT_TPGT;
1846cefaae1SJack Meng 
1856cefaae1SJack Meng 	if (boot_prop_entry->boot_tgt.sin_family == AF_INET) {
1866cefaae1SJack Meng 		entry->e_u.u_in4.s_addr =
1876cefaae1SJack Meng 		    boot_prop_entry->boot_tgt.tgt_ip_u.u_in4.s_addr;
1886cefaae1SJack Meng 		entry->e_insize = sizeof (struct in_addr);
1896cefaae1SJack Meng 	} else {
1906cefaae1SJack Meng 		(void) bcopy(
1916cefaae1SJack Meng 		    &boot_prop_entry->boot_tgt.tgt_ip_u.u_in6.s6_addr,
1926cefaae1SJack Meng 		    entry->e_u.u_in6.s6_addr, 16);
1936cefaae1SJack Meng 		entry->e_insize = sizeof (struct in6_addr);
1946cefaae1SJack Meng 	}
1956cefaae1SJack Meng 
1966cefaae1SJack Meng 	entry->e_port = boot_prop_entry->boot_tgt.tgt_port;
1976cefaae1SJack Meng 	entry->e_boot = B_TRUE;
1986cefaae1SJack Meng 	return (B_TRUE);
1996cefaae1SJack Meng }
2006cefaae1SJack Meng 
2016cefaae1SJack Meng /*
2026cefaae1SJack Meng  * Create the boot session
2036cefaae1SJack Meng  */
2046cefaae1SJack Meng static void
iscsi_boot_session_create(iscsi_hba_t * ihp,ib_boot_prop_t * boot_prop_table)2056cefaae1SJack Meng iscsi_boot_session_create(iscsi_hba_t *ihp,
2066cefaae1SJack Meng     ib_boot_prop_t	*boot_prop_table)
2076cefaae1SJack Meng {
2086cefaae1SJack Meng 	iSCSIDiscoveryMethod_t  dm;
2096cefaae1SJack Meng 	entry_t			e;
2106cefaae1SJack Meng 	iscsi_sockaddr_t	addr_dsc;
2116cefaae1SJack Meng 
2126cefaae1SJack Meng 	if (ihp == NULL || boot_prop_table == NULL) {
2136cefaae1SJack Meng 		return;
2146cefaae1SJack Meng 	}
2156cefaae1SJack Meng 
2166cefaae1SJack Meng 	if (!iscsid_ip_check(
2176cefaae1SJack Meng 	    (char *)&boot_prop_table->boot_tgt.tgt_ip_u)) {
2186cefaae1SJack Meng 		return;
2196cefaae1SJack Meng 	}
2206cefaae1SJack Meng 
2216cefaae1SJack Meng 	if (boot_prop_table->boot_tgt.tgt_name != NULL) {
2226cefaae1SJack Meng 		dm = iSCSIDiscoveryMethodStatic |
2236cefaae1SJack Meng 		    iSCSIDiscoveryMethodBoot;
2246cefaae1SJack Meng 		if (!iscsid_make_entry(boot_prop_table, &e))
2256cefaae1SJack Meng 			return;
2266cefaae1SJack Meng 		iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
2276cefaae1SJack Meng 		    e.e_port, &addr_dsc.sin);
2286cefaae1SJack Meng 
2296cefaae1SJack Meng 		(void) iscsid_add(ihp, dm, &addr_dsc.sin,
2306cefaae1SJack Meng 		    (char *)boot_prop_table->boot_tgt.tgt_name,
2316cefaae1SJack Meng 		    e.e_tpgt, &addr_dsc.sin);
2326cefaae1SJack Meng 	} else {
2336cefaae1SJack Meng 		dm = iSCSIDiscoveryMethodSendTargets |
2346cefaae1SJack Meng 		    iSCSIDiscoveryMethodBoot;
2356cefaae1SJack Meng 		if (!iscsid_make_entry(boot_prop_table, &e))
2366cefaae1SJack Meng 			return;
2376cefaae1SJack Meng 		iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
2386cefaae1SJack Meng 		    e.e_port, &addr_dsc.sin);
2396cefaae1SJack Meng 		iscsid_do_sendtgts(&e);
2406cefaae1SJack Meng 		(void) iscsid_login_tgt(ihp, NULL, dm,
2416cefaae1SJack Meng 		    &addr_dsc.sin);
2426cefaae1SJack Meng 	}
2436cefaae1SJack Meng }
2446cefaae1SJack Meng 
245fcf3ce44SJohn Forte /*
2464246c8e9SJack Meng  * iscsid_init -- to initialize stuffs related to iscsi daemon,
2474246c8e9SJack Meng  * and to create boot session if needed
248fcf3ce44SJohn Forte  */
249fcf3ce44SJohn Forte boolean_t
iscsid_init(iscsi_hba_t * ihp)2504246c8e9SJack Meng iscsid_init(iscsi_hba_t *ihp)
251fcf3ce44SJohn Forte {
2524246c8e9SJack Meng 	boolean_t		rval = B_TRUE;
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 	sema_init(&iscsid_config_semaphore, 1, NULL,
255fcf3ce44SJohn Forte 	    SEMA_DRIVER, NULL);
2564246c8e9SJack Meng 	persistent_init();
2574246c8e9SJack Meng 	iscsid_threads_create(ihp);
258fcf3ce44SJohn Forte 
259*7284664aSJoshua M. Clulow 	if (modrootloaded) {
260*7284664aSJoshua M. Clulow 		/*
261*7284664aSJoshua M. Clulow 		 * The root file system is available so we can load the
262*7284664aSJoshua M. Clulow 		 * persistent store.
263*7284664aSJoshua M. Clulow 		 */
2644246c8e9SJack Meng 		if (persistent_load() == B_TRUE) {
2654246c8e9SJack Meng 			ihp->hba_persistent_loaded = B_TRUE;
2666cefaae1SJack Meng 		} else {
2674246c8e9SJack Meng 			return (B_FALSE);
268fcf3ce44SJohn Forte 		}
269*7284664aSJoshua M. Clulow 	} else {
270*7284664aSJoshua M. Clulow 		/*
271*7284664aSJoshua M. Clulow 		 * If the root file system is not yet mounted then we _must_ be
272*7284664aSJoshua M. Clulow 		 * booting from an iSCSI device.  If not, we want to fail to
273*7284664aSJoshua M. Clulow 		 * attach so that we can try again after the VFS root is
274*7284664aSJoshua M. Clulow 		 * available.
275*7284664aSJoshua M. Clulow 		 */
276*7284664aSJoshua M. Clulow 		if (iscsiboot_prop == NULL) {
277*7284664aSJoshua M. Clulow 			return (B_FALSE);
278*7284664aSJoshua M. Clulow 		}
279fcf3ce44SJohn Forte 
2806cefaae1SJack Meng 		if (!iscsid_boot_init_config(ihp)) {
2816cefaae1SJack Meng 			rval = B_FALSE;
2826cefaae1SJack Meng 		} else {
2836cefaae1SJack Meng 			iscsi_boot_session_create(ihp, iscsiboot_prop);
2846cefaae1SJack Meng 			iscsi_boot_wd_handle =
2856cefaae1SJack Meng 			    iscsi_thread_create(ihp->hba_dip,
2866cefaae1SJack Meng 			    "BootWD", iscsid_thread_boot_wd, ihp);
287*7284664aSJoshua M. Clulow 			if (iscsi_boot_wd_handle != NULL) {
2886cefaae1SJack Meng 				rval = iscsi_thread_start(
2896cefaae1SJack Meng 				    iscsi_boot_wd_handle);
2906cefaae1SJack Meng 			} else {
2916cefaae1SJack Meng 				rval = B_FALSE;
2926cefaae1SJack Meng 			}
2936cefaae1SJack Meng 		}
2944246c8e9SJack Meng 		if (rval == B_FALSE) {
2954246c8e9SJack Meng 			cmn_err(CE_NOTE, "Initializaton of iscsi boot session"
2966cefaae1SJack Meng 			    " partially failed");
2976cefaae1SJack Meng 		}
2984246c8e9SJack Meng 	}
299fcf3ce44SJohn Forte 
3004246c8e9SJack Meng 	return (rval);
3014246c8e9SJack Meng }
3026cefaae1SJack Meng 
3034246c8e9SJack Meng /*
3044246c8e9SJack Meng  * iscsid_start -- start the iscsi initiator daemon, actually this code
3054246c8e9SJack Meng  * is just to enable discovery methods which are set enabled in
3064246c8e9SJack Meng  * persistent store, as an economic way to present the 'daemon' funtionality
3074246c8e9SJack Meng  */
3084246c8e9SJack Meng boolean_t
iscsid_start(iscsi_hba_t * ihp)309*7284664aSJoshua M. Clulow iscsid_start(iscsi_hba_t *ihp)
310*7284664aSJoshua M. Clulow {
3114246c8e9SJack Meng 	boolean_t		rval = B_FALSE;
3124246c8e9SJack Meng 	iSCSIDiscoveryMethod_t	dm;
3134246c8e9SJack Meng 	iSCSIDiscoveryMethod_t	*fdm;
3144246c8e9SJack Meng 
3154246c8e9SJack Meng 	rval = iscsid_init_config(ihp);
3164246c8e9SJack Meng 	if (rval == B_TRUE) {
3174246c8e9SJack Meng 		rval = iscsid_init_targets(ihp);
3184246c8e9SJack Meng 	}
3196cefaae1SJack Meng 
3204246c8e9SJack Meng 	if (rval == B_TRUE) {
3214246c8e9SJack Meng 		dm = persistent_disc_meth_get();
3224246c8e9SJack Meng 		rval = iscsid_enable_discovery(ihp, dm, B_TRUE);
3234246c8e9SJack Meng 		if (rval == B_TRUE) {
3244246c8e9SJack Meng 			iscsid_poke_discovery(ihp,
3254246c8e9SJack Meng 			    iSCSIDiscoveryMethodUnknown);
3264246c8e9SJack Meng 			(void) iscsid_login_tgt(ihp, NULL,
3274246c8e9SJack Meng 			    iSCSIDiscoveryMethodUnknown, NULL);
3286cefaae1SJack Meng 		}
3294246c8e9SJack Meng 	}
3304246c8e9SJack Meng 
3314246c8e9SJack Meng 	if (rval == B_FALSE) {
3324246c8e9SJack Meng 		/*
3334246c8e9SJack Meng 		 * In case of failure the events still need to be sent
3344246c8e9SJack Meng 		 * because the door daemon will pause until all these
3354246c8e9SJack Meng 		 * events have occurred.
3364246c8e9SJack Meng 		 */
3374246c8e9SJack Meng 		for (fdm = &for_failure[0]; *fdm !=
3384246c8e9SJack Meng 		    iSCSIDiscoveryMethodUnknown; fdm++) {
3394246c8e9SJack Meng 			/* ---- Send both start and end events ---- */
3404246c8e9SJack Meng 			iscsi_discovery_event(ihp, *fdm, B_TRUE);
3414246c8e9SJack Meng 			iscsi_discovery_event(ihp, *fdm, B_FALSE);
342fcf3ce44SJohn Forte 		}
343fcf3ce44SJohn Forte 	}
3444246c8e9SJack Meng 
3454246c8e9SJack Meng 	return (rval);
3464246c8e9SJack Meng }
3474246c8e9SJack Meng 
3484246c8e9SJack Meng /*
3494246c8e9SJack Meng  * iscsid_stop -- stop the iscsi initiator daemon, by disabling
3504246c8e9SJack Meng  * all the discovery methods first, and then try to stop all
35108dcd69cSJack Meng  * related threads. This is a try-best effort, leave any 'busy' device
35208dcd69cSJack Meng  * (and therefore session) there and just return.
3534246c8e9SJack Meng  */
3544246c8e9SJack Meng boolean_t
iscsid_stop(iscsi_hba_t * ihp)355*7284664aSJoshua M. Clulow iscsid_stop(iscsi_hba_t *ihp)
356*7284664aSJoshua M. Clulow {
3574246c8e9SJack Meng 	boolean_t		rval = B_FALSE;
358aefdd131Sbing zhao - Sun Microsystems - Beijing China 	iscsi_sess_t		*isp = NULL;
3594246c8e9SJack Meng 
36008dcd69cSJack Meng 	(void) iscsid_disable_discovery(ihp, ISCSI_ALL_DISCOVERY_METHODS);
3614246c8e9SJack Meng 
3624246c8e9SJack Meng 	/* final check */
3634246c8e9SJack Meng 	rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
3644246c8e9SJack Meng 	if (ihp->hba_sess_list == NULL) {
3654246c8e9SJack Meng 		rval = B_TRUE;
366aefdd131Sbing zhao - Sun Microsystems - Beijing China 	} else {
367aefdd131Sbing zhao - Sun Microsystems - Beijing China 		/*
368aefdd131Sbing zhao - Sun Microsystems - Beijing China 		 * If only boot session is left, that is OK.
36908dcd69cSJack Meng 		 * Otherwise, we should report that some sessions are left.
370aefdd131Sbing zhao - Sun Microsystems - Beijing China 		 */
371aefdd131Sbing zhao - Sun Microsystems - Beijing China 		rval = B_TRUE;
372aefdd131Sbing zhao - Sun Microsystems - Beijing China 		for (isp = ihp->hba_sess_list; isp != NULL;
373aefdd131Sbing zhao - Sun Microsystems - Beijing China 		    isp = isp->sess_next) {
374aefdd131Sbing zhao - Sun Microsystems - Beijing China 			if (isp->sess_boot == B_FALSE) {
375aefdd131Sbing zhao - Sun Microsystems - Beijing China 				rval = B_FALSE;
376aefdd131Sbing zhao - Sun Microsystems - Beijing China 				break;
377aefdd131Sbing zhao - Sun Microsystems - Beijing China 			}
378aefdd131Sbing zhao - Sun Microsystems - Beijing China 		}
3794246c8e9SJack Meng 	}
3804246c8e9SJack Meng 	rw_exit(&ihp->hba_sess_list_rwlock);
3814246c8e9SJack Meng 
382fcf3ce44SJohn Forte 	return (rval);
383fcf3ce44SJohn Forte }
384fcf3ce44SJohn Forte 
385fcf3ce44SJohn Forte /*
386fcf3ce44SJohn Forte  * iscsid_fini -- do whatever is required to clean up
387fcf3ce44SJohn Forte  */
388fcf3ce44SJohn Forte /* ARGSUSED */
389fcf3ce44SJohn Forte void
iscsid_fini()390fcf3ce44SJohn Forte iscsid_fini()
391fcf3ce44SJohn Forte {
3926cefaae1SJack Meng 	if (iscsi_boot_wd_handle != NULL) {
3936cefaae1SJack Meng 		iscsi_thread_destroy(iscsi_boot_wd_handle);
3946cefaae1SJack Meng 		iscsi_boot_wd_handle = NULL;
3956cefaae1SJack Meng 	}
3964246c8e9SJack Meng 	iscsid_threads_destroy();
397fcf3ce44SJohn Forte 	persistent_fini();
398fcf3ce44SJohn Forte 	sema_destroy(&iscsid_config_semaphore);
399fcf3ce44SJohn Forte }
400fcf3ce44SJohn Forte 
401fcf3ce44SJohn Forte /*
402fcf3ce44SJohn Forte  * iscsid_props -- returns discovery thread information, used by ioctl code
403fcf3ce44SJohn Forte  */
404fcf3ce44SJohn Forte void
iscsid_props(iSCSIDiscoveryProperties_t * props)405fcf3ce44SJohn Forte iscsid_props(iSCSIDiscoveryProperties_t *props)
406fcf3ce44SJohn Forte {
407fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t  dm;
408fcf3ce44SJohn Forte 
409fcf3ce44SJohn Forte 	dm = persistent_disc_meth_get();
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 	props->vers = ISCSI_INTERFACE_VERSION;
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 	/* ---- change once thread is implemented ---- */
414fcf3ce44SJohn Forte 	props->iSNSDiscoverySettable		= B_FALSE;
415fcf3ce44SJohn Forte 	props->SLPDiscoverySettable		= B_FALSE;
416fcf3ce44SJohn Forte 	props->StaticDiscoverySettable		= B_TRUE;
417fcf3ce44SJohn Forte 	props->SendTargetsDiscoverySettable	= B_TRUE;
418fcf3ce44SJohn Forte 	props->iSNSDiscoveryMethod		= iSNSDiscoveryMethodStatic;
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 	props->iSNSDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodISNS);
421fcf3ce44SJohn Forte 	props->StaticDiscoveryEnabled =
422fcf3ce44SJohn Forte 	    CHECK_METHOD(iSCSIDiscoveryMethodStatic);
423fcf3ce44SJohn Forte 	props->SendTargetsDiscoveryEnabled =
424fcf3ce44SJohn Forte 	    CHECK_METHOD(iSCSIDiscoveryMethodSendTargets);
425fcf3ce44SJohn Forte 	props->SLPDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodSLP);
426fcf3ce44SJohn Forte }
427fcf3ce44SJohn Forte 
428fcf3ce44SJohn Forte /*
429fcf3ce44SJohn Forte  * iscsid_enable_discovery - start specified discovery methods
430fcf3ce44SJohn Forte  */
431fcf3ce44SJohn Forte /* ARGSUSED */
432fcf3ce44SJohn Forte boolean_t
iscsid_enable_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t idm,boolean_t poke)433fcf3ce44SJohn Forte iscsid_enable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm,
434fcf3ce44SJohn Forte     boolean_t poke)
435fcf3ce44SJohn Forte {
436fcf3ce44SJohn Forte 	boolean_t		rval = B_TRUE;
437fcf3ce44SJohn Forte 	iscsid_thr_table	*dt;
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	/*
440fcf3ce44SJohn Forte 	 * start the specified discovery method(s)
441fcf3ce44SJohn Forte 	 */
442fcf3ce44SJohn Forte 	for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
443fcf3ce44SJohn Forte 	    dt++) {
444fcf3ce44SJohn Forte 		if (idm & dt->method) {
445fcf3ce44SJohn Forte 			if (dt->thr_id != NULL) {
446fcf3ce44SJohn Forte 				rval = iscsi_thread_start(dt->thr_id);
447fcf3ce44SJohn Forte 				if (rval == B_FALSE) {
448fcf3ce44SJohn Forte 					break;
449fcf3ce44SJohn Forte 				}
450fcf3ce44SJohn Forte 				if (poke == B_TRUE) {
45149311b35SJack Meng 					(void) iscsi_thread_send_wakeup(
45249311b35SJack Meng 					    dt->thr_id);
453fcf3ce44SJohn Forte 				}
454fcf3ce44SJohn Forte 			} else {
455fcf3ce44SJohn Forte 				/*
456fcf3ce44SJohn Forte 				 * unexpected condition.  The threads for each
457fcf3ce44SJohn Forte 				 * discovery method should have started at
458fcf3ce44SJohn Forte 				 * initialization
459fcf3ce44SJohn Forte 				 */
460fcf3ce44SJohn Forte 				ASSERT(B_FALSE);
461fcf3ce44SJohn Forte 			}
462fcf3ce44SJohn Forte 		}
463fcf3ce44SJohn Forte 	} /* END for() */
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 	return (rval);
466fcf3ce44SJohn Forte }
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte /*
470fcf3ce44SJohn Forte  * iscsid_disable_discovery - stop specified discovery methods
471fcf3ce44SJohn Forte  */
472fcf3ce44SJohn Forte boolean_t
iscsid_disable_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t idm)473fcf3ce44SJohn Forte iscsid_disable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm)
474fcf3ce44SJohn Forte {
475fcf3ce44SJohn Forte 	boolean_t		rval = B_TRUE;
476fcf3ce44SJohn Forte 	iscsid_thr_table	*dt;
477fcf3ce44SJohn Forte 
478fcf3ce44SJohn Forte 	/*
479fcf3ce44SJohn Forte 	 * stop the specified discovery method(s)
480fcf3ce44SJohn Forte 	 */
481fcf3ce44SJohn Forte 	for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
482fcf3ce44SJohn Forte 	    dt++) {
483fcf3ce44SJohn Forte 		if (idm & dt->method) {
484fcf3ce44SJohn Forte 
485fcf3ce44SJohn Forte 			/* signal discovery event change - begin */
486fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp, dt->method, B_TRUE);
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 			/* Attempt to logout of all associated targets */
489fcf3ce44SJohn Forte 			rval = iscsid_del(ihp, NULL, dt->method, NULL);
490fcf3ce44SJohn Forte 			if (rval == B_TRUE) {
491fcf3ce44SJohn Forte 				/* Successfully logged out of targets */
492fcf3ce44SJohn Forte 				if (dt->thr_id != NULL) {
493fcf3ce44SJohn Forte 					rval = iscsi_thread_stop(dt->thr_id);
494fcf3ce44SJohn Forte 					if (rval == B_FALSE) {
495fcf3ce44SJohn Forte 						/*
496fcf3ce44SJohn Forte 						 * signal discovery
497fcf3ce44SJohn Forte 						 * event change - end
498fcf3ce44SJohn Forte 						 */
499fcf3ce44SJohn Forte 						iscsi_discovery_event(ihp,
500fcf3ce44SJohn Forte 						    dt->method, B_FALSE);
501fcf3ce44SJohn Forte 						break;
502fcf3ce44SJohn Forte 					}
503fcf3ce44SJohn Forte 
504fcf3ce44SJohn Forte 				} else {
505fcf3ce44SJohn Forte 					/*
506fcf3ce44SJohn Forte 					 * unexpected condition.  The threads
507fcf3ce44SJohn Forte 					 * for each discovery method should
508fcf3ce44SJohn Forte 					 * have started at initialization
509fcf3ce44SJohn Forte 					 */
510fcf3ce44SJohn Forte 					ASSERT(B_FALSE);
511fcf3ce44SJohn Forte 				}
512fcf3ce44SJohn Forte 			}
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 			/* signal discovery event change - end */
515fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp, dt->method, B_FALSE);
516fcf3ce44SJohn Forte 
517fcf3ce44SJohn Forte 		}
518fcf3ce44SJohn Forte 	} /* END for() */
519fcf3ce44SJohn Forte 
520fcf3ce44SJohn Forte 	return (rval);
521fcf3ce44SJohn Forte }
522fcf3ce44SJohn Forte 
523fcf3ce44SJohn Forte /*
524fcf3ce44SJohn Forte  * iscsid_poke_discovery - wakeup discovery methods to find any new targets
525fcf3ce44SJohn Forte  * and wait for all discovery processes to complete.
526fcf3ce44SJohn Forte  */
527fcf3ce44SJohn Forte void
iscsid_poke_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t method)528fcf3ce44SJohn Forte iscsid_poke_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method)
529fcf3ce44SJohn Forte {
530fcf3ce44SJohn Forte #define	ISCSI_DISCOVERY_DELAY	1
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t	dm;
533fcf3ce44SJohn Forte 	iscsid_thr_table	*dt;
53449311b35SJack Meng 	boolean_t		send_wakeup;
535fcf3ce44SJohn Forte 
536fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
537fcf3ce44SJohn Forte 
538fcf3ce44SJohn Forte 	/* reset discovery flags */
539fcf3ce44SJohn Forte 	mutex_enter(&ihp->hba_discovery_events_mutex);
540fcf3ce44SJohn Forte 	ihp->hba_discovery_in_progress = B_TRUE;
541fcf3ce44SJohn Forte 	ihp->hba_discovery_events = iSCSIDiscoveryMethodUnknown;
542fcf3ce44SJohn Forte 	mutex_exit(&ihp->hba_discovery_events_mutex);
543fcf3ce44SJohn Forte 
544fcf3ce44SJohn Forte 	/* start all enabled discovery methods */
545fcf3ce44SJohn Forte 	dm = persistent_disc_meth_get();
546fcf3ce44SJohn Forte 	for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
547fcf3ce44SJohn Forte 	    dt++) {
54849311b35SJack Meng 		send_wakeup = B_FALSE;
54949311b35SJack Meng 
550fcf3ce44SJohn Forte 		if ((method == iSCSIDiscoveryMethodUnknown) ||
551fcf3ce44SJohn Forte 		    (method == dt->method)) {
552fcf3ce44SJohn Forte 			if ((dm & dt->method) && (dt->thr_id != NULL)) {
55349311b35SJack Meng 				if (iscsi_thread_send_wakeup(dt->thr_id) ==
55449311b35SJack Meng 				    B_TRUE) {
55549311b35SJack Meng 					send_wakeup = B_TRUE;
55649311b35SJack Meng 				}
557fcf3ce44SJohn Forte 			}
55849311b35SJack Meng 		}
55949311b35SJack Meng 
56049311b35SJack Meng 		if (send_wakeup == B_FALSE) {
561fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp, dt->method, B_TRUE);
562fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp, dt->method, B_FALSE);
563fcf3ce44SJohn Forte 		}
564fcf3ce44SJohn Forte 	}
565fcf3ce44SJohn Forte 
566fcf3ce44SJohn Forte 	mutex_enter(&ihp->hba_discovery_events_mutex);
567fcf3ce44SJohn Forte 	while (ihp->hba_discovery_events != ISCSI_ALL_DISCOVERY_METHODS) {
568fcf3ce44SJohn Forte 		mutex_exit(&ihp->hba_discovery_events_mutex);
569fcf3ce44SJohn Forte 		delay(SEC_TO_TICK(ISCSI_DISCOVERY_DELAY));
570fcf3ce44SJohn Forte 		mutex_enter(&ihp->hba_discovery_events_mutex);
571fcf3ce44SJohn Forte 	}
572fcf3ce44SJohn Forte 	ihp->hba_discovery_in_progress = B_FALSE;
573fcf3ce44SJohn Forte 	mutex_exit(&ihp->hba_discovery_events_mutex);
574fcf3ce44SJohn Forte 
575fcf3ce44SJohn Forte }
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte /*
578fcf3ce44SJohn Forte  * iscsid_do_sendtgts - issue send targets command to the given discovery
579fcf3ce44SJohn Forte  * address and then add the discovered targets to the discovery queue
580fcf3ce44SJohn Forte  */
581fcf3ce44SJohn Forte void
iscsid_do_sendtgts(entry_t * disc_addr)582fcf3ce44SJohn Forte iscsid_do_sendtgts(entry_t *disc_addr)
583fcf3ce44SJohn Forte {
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte #define	SENDTGTS_DEFAULT_NUM_TARGETS    10
586fcf3ce44SJohn Forte 
587fcf3ce44SJohn Forte 	int			stl_sz;
588fcf3ce44SJohn Forte 	int			stl_num_tgts = SENDTGTS_DEFAULT_NUM_TARGETS;
589fcf3ce44SJohn Forte 	iscsi_sendtgts_list_t	*stl_hdr = NULL;
590fcf3ce44SJohn Forte 	boolean_t		retry = B_TRUE;
591fcf3ce44SJohn Forte 	char			inp_buf[INET6_ADDRSTRLEN];
592fcf3ce44SJohn Forte 	const char		*ip;
593fcf3ce44SJohn Forte 	int			ctr;
594fcf3ce44SJohn Forte 	int			rc;
5956cefaae1SJack Meng 	iscsi_hba_t		*ihp;
5966cefaae1SJack Meng 	iSCSIDiscoveryMethod_t  dm = iSCSIDiscoveryMethodSendTargets;
597fcf3ce44SJohn Forte 
598fcf3ce44SJohn Forte 	/* allocate and initialize sendtargets list header */
599fcf3ce44SJohn Forte 	stl_sz = sizeof (*stl_hdr) + ((stl_num_tgts - 1) *
600fcf3ce44SJohn Forte 	    sizeof (iscsi_sendtgts_entry_t));
601fcf3ce44SJohn Forte 	stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
602fcf3ce44SJohn Forte 
603fcf3ce44SJohn Forte retry_sendtgts:
604fcf3ce44SJohn Forte 	stl_hdr->stl_in_cnt = stl_num_tgts;
605fcf3ce44SJohn Forte 	bcopy(disc_addr, &(stl_hdr->stl_entry),
606fcf3ce44SJohn Forte 	    sizeof (stl_hdr->stl_entry));
607fcf3ce44SJohn Forte 	stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte 	/* lock interface so only one SendTargets operation occurs */
610fcf3ce44SJohn Forte 	if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
611fcf3ce44SJohn Forte 		cmn_err(CE_NOTE, "!iscsi discovery failure - SendTargets. "
612fcf3ce44SJohn Forte 		    "failure to get soft state");
613fcf3ce44SJohn Forte 		kmem_free(stl_hdr, stl_sz);
614fcf3ce44SJohn Forte 		return;
615fcf3ce44SJohn Forte 	}
616fcf3ce44SJohn Forte 	sema_p(&ihp->hba_sendtgts_semaphore);
617fcf3ce44SJohn Forte 	rc = iscsi_ioctl_sendtgts_get(ihp, stl_hdr);
618fcf3ce44SJohn Forte 	sema_v(&ihp->hba_sendtgts_semaphore);
619fcf3ce44SJohn Forte 	if (rc) {
620fcf3ce44SJohn Forte 		ip = inet_ntop((disc_addr->e_insize ==
621fcf3ce44SJohn Forte 		    sizeof (struct in_addr) ? AF_INET : AF_INET6),
622fcf3ce44SJohn Forte 		    &disc_addr->e_u, inp_buf, sizeof (inp_buf));
623fcf3ce44SJohn Forte 		cmn_err(CE_NOTE,
624fcf3ce44SJohn Forte 		    "iscsi discovery failure - SendTargets (%s)\n", ip);
625fcf3ce44SJohn Forte 		kmem_free(stl_hdr, stl_sz);
626fcf3ce44SJohn Forte 		return;
627fcf3ce44SJohn Forte 	}
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	/* check if all targets received */
630fcf3ce44SJohn Forte 	if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
631fcf3ce44SJohn Forte 		if (retry == B_TRUE) {
632fcf3ce44SJohn Forte 			stl_num_tgts = stl_hdr->stl_out_cnt;
633fcf3ce44SJohn Forte 			kmem_free(stl_hdr, stl_sz);
634fcf3ce44SJohn Forte 			stl_sz = sizeof (*stl_hdr) +
635fcf3ce44SJohn Forte 			    ((stl_num_tgts - 1) *
636fcf3ce44SJohn Forte 			    sizeof (iscsi_sendtgts_entry_t));
637fcf3ce44SJohn Forte 			stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
638fcf3ce44SJohn Forte 			retry = B_FALSE;
639fcf3ce44SJohn Forte 			goto retry_sendtgts;
640fcf3ce44SJohn Forte 		} else {
641fcf3ce44SJohn Forte 			ip = inet_ntop((disc_addr->e_insize ==
642fcf3ce44SJohn Forte 			    sizeof (struct in_addr) ?
643fcf3ce44SJohn Forte 			    AF_INET : AF_INET6), &disc_addr->e_u,
644fcf3ce44SJohn Forte 			    inp_buf, sizeof (inp_buf));
645fcf3ce44SJohn Forte 			cmn_err(CE_NOTE, "iscsi discovery failure - "
646fcf3ce44SJohn Forte 			    "SendTargets overflow (%s)\n", ip);
647fcf3ce44SJohn Forte 			kmem_free(stl_hdr, stl_sz);
648fcf3ce44SJohn Forte 			return;
649fcf3ce44SJohn Forte 		}
650fcf3ce44SJohn Forte 	}
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte 	for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
653fcf3ce44SJohn Forte 		iscsi_sockaddr_t addr_dsc;
654fcf3ce44SJohn Forte 		iscsi_sockaddr_t addr_tgt;
655fcf3ce44SJohn Forte 
656fcf3ce44SJohn Forte 		iscsid_addr_to_sockaddr(disc_addr->e_insize,
657fcf3ce44SJohn Forte 		    &disc_addr->e_u, disc_addr->e_port, &addr_dsc.sin);
658fcf3ce44SJohn Forte 		iscsid_addr_to_sockaddr(
659fcf3ce44SJohn Forte 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize,
660fcf3ce44SJohn Forte 		    &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
661fcf3ce44SJohn Forte 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_port,
662fcf3ce44SJohn Forte 		    &addr_tgt.sin);
6636cefaae1SJack Meng 		if (disc_addr->e_boot == B_TRUE) {
6646cefaae1SJack Meng 			dm = dm | iSCSIDiscoveryMethodBoot;
6656cefaae1SJack Meng 		}
6666cefaae1SJack Meng 		(void) iscsid_add(ihp, dm,
667fcf3ce44SJohn Forte 		    &addr_dsc.sin, (char *)stl_hdr->stl_list[ctr].ste_name,
668fcf3ce44SJohn Forte 		    stl_hdr->stl_list[ctr].ste_tpgt,
669fcf3ce44SJohn Forte 		    &addr_tgt.sin);
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 	kmem_free(stl_hdr, stl_sz);
672fcf3ce44SJohn Forte }
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte void
iscsid_do_isns_query_one_server(iscsi_hba_t * ihp,entry_t * isns_server)675fcf3ce44SJohn Forte iscsid_do_isns_query_one_server(iscsi_hba_t *ihp, entry_t *isns_server)
676fcf3ce44SJohn Forte {
677fcf3ce44SJohn Forte 	int pg_sz, query_status;
678fcf3ce44SJohn Forte 	iscsi_addr_t *ap;
679fcf3ce44SJohn Forte 	isns_portal_group_list_t *pg_list;
680fcf3ce44SJohn Forte 
681fcf3ce44SJohn Forte 	ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
682fcf3ce44SJohn Forte 	ap->a_port = isns_server->e_port;
683fcf3ce44SJohn Forte 	ap->a_addr.i_insize = isns_server->e_insize;
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte 	if (isns_server->e_insize == sizeof (struct in_addr)) {
686fcf3ce44SJohn Forte 		ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr);
687fcf3ce44SJohn Forte 	} else if (isns_server->e_insize == sizeof (struct in6_addr)) {
688fcf3ce44SJohn Forte 		bcopy(&(isns_server->e_u.u_in6.s6_addr),
689fcf3ce44SJohn Forte 		    ap->a_addr.i_addr.in6.s6_addr, 16);
690fcf3ce44SJohn Forte 	} else {
691fcf3ce44SJohn Forte 		kmem_free(ap, sizeof (iscsi_addr_t));
692fcf3ce44SJohn Forte 		return;
693fcf3ce44SJohn Forte 	}
694fcf3ce44SJohn Forte 
695fcf3ce44SJohn Forte 	pg_list = NULL;
696fcf3ce44SJohn Forte 	query_status = isns_query_one_server(
697fcf3ce44SJohn Forte 	    ap, ihp->hba_isid,
698fcf3ce44SJohn Forte 	    ihp->hba_name, ihp->hba_alias,
699fcf3ce44SJohn Forte 	    ISNS_INITIATOR_NODE_TYPE, &pg_list);
700fcf3ce44SJohn Forte 	kmem_free(ap, sizeof (iscsi_addr_t));
701fcf3ce44SJohn Forte 	if (query_status != isns_ok || pg_list == NULL) {
702fcf3ce44SJohn Forte 		DTRACE_PROBE1(iscsid_do_isns_query_one_server_status,
703fcf3ce44SJohn Forte 		    int, query_status);
704fcf3ce44SJohn Forte 		return;
705fcf3ce44SJohn Forte 	}
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 	iscsid_add_pg_list_to_cache(ihp, pg_list);
708fcf3ce44SJohn Forte 	pg_sz = sizeof (isns_portal_group_list_t);
709fcf3ce44SJohn Forte 	if (pg_list->pg_out_cnt > 0) {
710fcf3ce44SJohn Forte 		pg_sz += (pg_list->pg_out_cnt - 1) *
711fcf3ce44SJohn Forte 		    sizeof (isns_portal_group_t);
712fcf3ce44SJohn Forte 	}
713fcf3ce44SJohn Forte 	kmem_free(pg_list, pg_sz);
714fcf3ce44SJohn Forte }
715fcf3ce44SJohn Forte 
716fcf3ce44SJohn Forte void
iscsid_do_isns_query(iscsi_hba_t * ihp)717fcf3ce44SJohn Forte iscsid_do_isns_query(iscsi_hba_t *ihp)
718fcf3ce44SJohn Forte {
719fcf3ce44SJohn Forte 	int pg_sz, query_status;
720fcf3ce44SJohn Forte 	isns_portal_group_list_t *pg_list;
721fcf3ce44SJohn Forte 
722fcf3ce44SJohn Forte 	pg_list = NULL;
723fcf3ce44SJohn Forte 	query_status = isns_query(ihp->hba_isid,
724fcf3ce44SJohn Forte 	    ihp->hba_name,
725fcf3ce44SJohn Forte 	    ihp->hba_alias,
726fcf3ce44SJohn Forte 	    ISNS_INITIATOR_NODE_TYPE,
727fcf3ce44SJohn Forte 	    &pg_list);
7286362598eSbing zhao - Sun Microsystems - Beijing China 
7296362598eSbing zhao - Sun Microsystems - Beijing China 	if (pg_list == NULL) {
7306362598eSbing zhao - Sun Microsystems - Beijing China 		DTRACE_PROBE1(iscsid_do_isns_query_status,
7316362598eSbing zhao - Sun Microsystems - Beijing China 		    int, query_status);
7326362598eSbing zhao - Sun Microsystems - Beijing China 		return;
7336362598eSbing zhao - Sun Microsystems - Beijing China 	}
7346362598eSbing zhao - Sun Microsystems - Beijing China 
735fcf3ce44SJohn Forte 	if ((query_status != isns_ok &&
7366362598eSbing zhao - Sun Microsystems - Beijing China 	    query_status != isns_op_partially_failed)) {
737fcf3ce44SJohn Forte 		DTRACE_PROBE1(iscsid_do_isns_query_status,
738fcf3ce44SJohn Forte 		    int, query_status);
7396362598eSbing zhao - Sun Microsystems - Beijing China 		pg_sz = sizeof (isns_portal_group_list_t);
7406362598eSbing zhao - Sun Microsystems - Beijing China 		if (pg_list->pg_out_cnt > 0) {
7416362598eSbing zhao - Sun Microsystems - Beijing China 			pg_sz += (pg_list->pg_out_cnt - 1) *
7426362598eSbing zhao - Sun Microsystems - Beijing China 			    sizeof (isns_portal_group_t);
7436362598eSbing zhao - Sun Microsystems - Beijing China 		}
7446362598eSbing zhao - Sun Microsystems - Beijing China 		kmem_free(pg_list, pg_sz);
745fcf3ce44SJohn Forte 		return;
746fcf3ce44SJohn Forte 	}
7476362598eSbing zhao - Sun Microsystems - Beijing China 
748fcf3ce44SJohn Forte 	iscsid_add_pg_list_to_cache(ihp, pg_list);
749fcf3ce44SJohn Forte 
750fcf3ce44SJohn Forte 	pg_sz = sizeof (isns_portal_group_list_t);
751fcf3ce44SJohn Forte 	if (pg_list->pg_out_cnt > 0) {
752fcf3ce44SJohn Forte 		pg_sz += (pg_list->pg_out_cnt - 1) *
753fcf3ce44SJohn Forte 		    sizeof (isns_portal_group_t);
754fcf3ce44SJohn Forte 	}
755fcf3ce44SJohn Forte 	kmem_free(pg_list, pg_sz);
756fcf3ce44SJohn Forte }
757fcf3ce44SJohn Forte 
758fcf3ce44SJohn Forte /*
759fcf3ce44SJohn Forte  * iscsid_config_one - for the given target name, attempt
760fcf3ce44SJohn Forte  * to login to all targets associated with name.  If target
761fcf3ce44SJohn Forte  * name is not found in discovery queue, reset the discovery
762fcf3ce44SJohn Forte  * queue, kick the discovery processes, and then retry.
763fcf3ce44SJohn Forte  *
764fcf3ce44SJohn Forte  * NOTE: The caller of this function must hold the
765fcf3ce44SJohn Forte  *	iscsid_config_semaphore across this call.
766fcf3ce44SJohn Forte  */
767fcf3ce44SJohn Forte void
iscsid_config_one(iscsi_hba_t * ihp,char * name,boolean_t protect)768fcf3ce44SJohn Forte iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect)
769fcf3ce44SJohn Forte {
7706cefaae1SJack Meng 	boolean_t	rc	    =	B_FALSE;
7716cefaae1SJack Meng 	int		retry	    =	0;
7726cefaae1SJack Meng 	int		lun_online  =	0;
7736cefaae1SJack Meng 	int		cur_sec	    =	0;
7746cefaae1SJack Meng 
7756cefaae1SJack Meng 	if (!modrootloaded && (iscsiboot_prop != NULL)) {
7766cefaae1SJack Meng 		if (!iscsi_configroot_printed) {
7776cefaae1SJack Meng 			cmn_err(CE_NOTE, "Configuring"
7786cefaae1SJack Meng 			    " iSCSI boot session...");
7796cefaae1SJack Meng 			iscsi_configroot_printed = B_TRUE;
7806cefaae1SJack Meng 		}
78130e7468fSPeter Dunlap 		if (iscsi_net_up == 0) {
782bbe72583SJack Meng 			if (iscsi_net_interface(B_FALSE) ==
783bbe72583SJack Meng 			    ISCSI_STATUS_SUCCESS) {
78430e7468fSPeter Dunlap 				iscsi_net_up = 1;
78530e7468fSPeter Dunlap 			} else {
78630e7468fSPeter Dunlap 				cmn_err(CE_WARN, "Failed to configure interface"
78730e7468fSPeter Dunlap 				    " for iSCSI boot session");
78830e7468fSPeter Dunlap 				return;
78930e7468fSPeter Dunlap 			}
79030e7468fSPeter Dunlap 		}
7916cefaae1SJack Meng 		while (rc == B_FALSE && retry <
7926cefaae1SJack Meng 		    iscsi_configroot_retry) {
7936cefaae1SJack Meng 			rc = iscsid_login_tgt(ihp, name,
7946cefaae1SJack Meng 			    iSCSIDiscoveryMethodBoot, NULL);
7956cefaae1SJack Meng 			if (rc == B_FALSE) {
7966cefaae1SJack Meng 				/*
7976cefaae1SJack Meng 				 * create boot session
7986cefaae1SJack Meng 				 */
7996cefaae1SJack Meng 				iscsi_boot_session_create(ihp,
8006cefaae1SJack Meng 				    iscsiboot_prop);
801f53e1f19SJack Meng 				retry++;
802f53e1f19SJack Meng 				continue;
803f53e1f19SJack Meng 			}
804f53e1f19SJack Meng 			rc = iscsid_check_active_boot_conn(ihp);
805f53e1f19SJack Meng 			if (rc == B_FALSE) {
8066cefaae1SJack Meng 				/*
807f53e1f19SJack Meng 				 * no active connection for the boot
808f53e1f19SJack Meng 				 * session, retry the login until
809f53e1f19SJack Meng 				 * one is found or the retry count
810f53e1f19SJack Meng 				 * is exceeded
8116cefaae1SJack Meng 				 */
812f53e1f19SJack Meng 				delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
813f53e1f19SJack Meng 				retry++;
814f53e1f19SJack Meng 				continue;
8156cefaae1SJack Meng 			}
816f53e1f19SJack Meng 			/*
817f53e1f19SJack Meng 			 * The boot session has been created with active
818f53e1f19SJack Meng 			 * connection. If the target lun has not been online,
819f53e1f19SJack Meng 			 * we should wait here for a while
820f53e1f19SJack Meng 			 */
821f53e1f19SJack Meng 			do {
822f53e1f19SJack Meng 				lun_online =
823f53e1f19SJack Meng 				    iscsiboot_prop->boot_tgt.lun_online;
824f53e1f19SJack Meng 				if (lun_online == 0) {
825f53e1f19SJack Meng 					delay(SEC_TO_TICK(
826f53e1f19SJack Meng 					    ISCSI_CONFIGROOT_DELAY));
827f53e1f19SJack Meng 					cur_sec++;
828f53e1f19SJack Meng 				}
829f53e1f19SJack Meng 			} while ((lun_online == 0) &&
830f53e1f19SJack Meng 			    (cur_sec < iscsi_boot_max_delay));
8316cefaae1SJack Meng 			retry++;
8326cefaae1SJack Meng 		}
8336cefaae1SJack Meng 		if (!rc) {
8346cefaae1SJack Meng 			cmn_err(CE_WARN, "Failed to configure iSCSI"
8356cefaae1SJack Meng 			    " boot session");
8366cefaae1SJack Meng 		}
8376cefaae1SJack Meng 	} else {
8386cefaae1SJack Meng 		rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown,
8396cefaae1SJack Meng 		    NULL);
840fcf3ce44SJohn Forte 		/*
8416cefaae1SJack Meng 		 * If we didn't login to the device we might have
8426cefaae1SJack Meng 		 * to update our discovery information and attempt
8436cefaae1SJack Meng 		 * the login again.
844fcf3ce44SJohn Forte 		 */
8456cefaae1SJack Meng 		if (rc == B_FALSE) {
8466cefaae1SJack Meng 			/*
8476cefaae1SJack Meng 			 * Stale /dev links can cause us to get floods
8486cefaae1SJack Meng 			 * of config requests.  Prevent these repeated
8496cefaae1SJack Meng 			 * requests from causing unneeded discovery updates
8506cefaae1SJack Meng 			 * if ISCSI_CONFIG_STORM_PROTECT is set.
8516cefaae1SJack Meng 			 */
8526cefaae1SJack Meng 			if ((protect == B_FALSE) ||
8536cefaae1SJack Meng 			    (ddi_get_lbolt() > ihp->hba_config_lbolt +
8546cefaae1SJack Meng 			    SEC_TO_TICK(ihp->hba_config_storm_delay))) {
8556cefaae1SJack Meng 				ihp->hba_config_lbolt = ddi_get_lbolt();
8566cefaae1SJack Meng 				iscsid_poke_discovery(ihp,
8576cefaae1SJack Meng 				    iSCSIDiscoveryMethodUnknown);
8586cefaae1SJack Meng 				(void) iscsid_login_tgt(ihp, name,
8596cefaae1SJack Meng 				    iSCSIDiscoveryMethodUnknown, NULL);
8606cefaae1SJack Meng 			}
861fcf3ce44SJohn Forte 		}
862fcf3ce44SJohn Forte 	}
863fcf3ce44SJohn Forte }
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte /*
866fcf3ce44SJohn Forte  * iscsid_config_all - reset the discovery queue, kick the
867fcf3ce44SJohn Forte  * discovery processes, and login to all targets found
868fcf3ce44SJohn Forte  *
869fcf3ce44SJohn Forte  * NOTE: The caller of this function must hold the
870fcf3ce44SJohn Forte  *	iscsid_config_semaphore across this call.
871fcf3ce44SJohn Forte  */
872fcf3ce44SJohn Forte void
iscsid_config_all(iscsi_hba_t * ihp,boolean_t protect)873fcf3ce44SJohn Forte iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect)
874fcf3ce44SJohn Forte {
8756cefaae1SJack Meng 	boolean_t	rc		= B_FALSE;
8766cefaae1SJack Meng 	int		retry	= 0;
8776cefaae1SJack Meng 	int		lun_online  = 0;
8786cefaae1SJack Meng 	int		cur_sec	= 0;
8796cefaae1SJack Meng 
8806cefaae1SJack Meng 	if (!modrootloaded && iscsiboot_prop != NULL) {
8816cefaae1SJack Meng 		if (!iscsi_configroot_printed) {
8826cefaae1SJack Meng 			cmn_err(CE_NOTE, "Configuring"
8836cefaae1SJack Meng 			    " iSCSI boot session...");
8846cefaae1SJack Meng 			iscsi_configroot_printed = B_TRUE;
8856cefaae1SJack Meng 		}
88630e7468fSPeter Dunlap 		if (iscsi_net_up == 0) {
887bbe72583SJack Meng 			if (iscsi_net_interface(B_FALSE) ==
888bbe72583SJack Meng 			    ISCSI_STATUS_SUCCESS) {
88930e7468fSPeter Dunlap 				iscsi_net_up = 1;
89030e7468fSPeter Dunlap 			}
89130e7468fSPeter Dunlap 		}
8926cefaae1SJack Meng 		while (rc == B_FALSE && retry <
8936cefaae1SJack Meng 		    iscsi_configroot_retry) {
8946cefaae1SJack Meng 			rc = iscsid_login_tgt(ihp, NULL,
8956cefaae1SJack Meng 			    iSCSIDiscoveryMethodBoot, NULL);
8966cefaae1SJack Meng 			if (rc == B_FALSE) {
8976cefaae1SJack Meng 				/*
8986cefaae1SJack Meng 				 * No boot session has been created.
8996cefaae1SJack Meng 				 * We would like to create the boot
9006cefaae1SJack Meng 				 * Session first.
9016cefaae1SJack Meng 				 */
9026cefaae1SJack Meng 				iscsi_boot_session_create(ihp,
9036cefaae1SJack Meng 				    iscsiboot_prop);
904f53e1f19SJack Meng 				retry++;
905f53e1f19SJack Meng 				continue;
906f53e1f19SJack Meng 			}
907f53e1f19SJack Meng 			rc = iscsid_check_active_boot_conn(ihp);
908f53e1f19SJack Meng 			if (rc == B_FALSE) {
9096cefaae1SJack Meng 				/*
910f53e1f19SJack Meng 				 * no active connection for the boot
911f53e1f19SJack Meng 				 * session, retry the login until
912f53e1f19SJack Meng 				 * one is found or the retry count
913f53e1f19SJack Meng 				 * is exceeded
9146cefaae1SJack Meng 				 */
915f53e1f19SJack Meng 				delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
916f53e1f19SJack Meng 				retry++;
917f53e1f19SJack Meng 				continue;
9186cefaae1SJack Meng 			}
919f53e1f19SJack Meng 			/*
920f53e1f19SJack Meng 			 * The boot session has been created with active
921f53e1f19SJack Meng 			 * connection. If the target lun has not been online,
922f53e1f19SJack Meng 			 * we should wait here for a while
923f53e1f19SJack Meng 			 */
924f53e1f19SJack Meng 			do {
925f53e1f19SJack Meng 				lun_online =
926f53e1f19SJack Meng 				    iscsiboot_prop->boot_tgt.lun_online;
927f53e1f19SJack Meng 				if (lun_online == 0) {
928f53e1f19SJack Meng 					delay(SEC_TO_TICK(
929f53e1f19SJack Meng 					    ISCSI_CONFIGROOT_DELAY));
930f53e1f19SJack Meng 					cur_sec++;
931f53e1f19SJack Meng 				}
932f53e1f19SJack Meng 			} while ((lun_online == 0) &&
933f53e1f19SJack Meng 			    (cur_sec < iscsi_boot_max_delay));
9346cefaae1SJack Meng 			retry++;
9356cefaae1SJack Meng 		}
9366cefaae1SJack Meng 		if (!rc) {
9376cefaae1SJack Meng 			cmn_err(CE_WARN, "Failed to configure"
9386cefaae1SJack Meng 			    " boot session");
9396cefaae1SJack Meng 		}
9406cefaae1SJack Meng 	} else {
9416cefaae1SJack Meng 		/*
9426cefaae1SJack Meng 		 * Stale /dev links can cause us to get floods
9436cefaae1SJack Meng 		 * of config requests.  Prevent these repeated
9446cefaae1SJack Meng 		 * requests from causing unneeded discovery updates
9456cefaae1SJack Meng 		 * if ISCSI_CONFIG_STORM_PROTECT is set.
9466cefaae1SJack Meng 		 */
9476cefaae1SJack Meng 		if ((protect == B_FALSE) ||
9486cefaae1SJack Meng 		    (ddi_get_lbolt() > ihp->hba_config_lbolt +
9496cefaae1SJack Meng 		    SEC_TO_TICK(ihp->hba_config_storm_delay))) {
9506cefaae1SJack Meng 			ihp->hba_config_lbolt = ddi_get_lbolt();
9516cefaae1SJack Meng 			iscsid_poke_discovery(ihp,
9526cefaae1SJack Meng 			    iSCSIDiscoveryMethodUnknown);
9536cefaae1SJack Meng 		}
9546cefaae1SJack Meng 		(void) iscsid_login_tgt(ihp, NULL,
9556cefaae1SJack Meng 		    iSCSIDiscoveryMethodUnknown, NULL);
9566cefaae1SJack Meng 	}
957fcf3ce44SJohn Forte }
958fcf3ce44SJohn Forte 
959fcf3ce44SJohn Forte /*
960fcf3ce44SJohn Forte  * isns_scn_callback - iSNS client received an SCN
961fcf3ce44SJohn Forte  *
962fcf3ce44SJohn Forte  * This code processes the iSNS client SCN events.  These
963fcf3ce44SJohn Forte  * could relate to the addition, removal, or update of a
964fcf3ce44SJohn Forte  * logical unit.
965fcf3ce44SJohn Forte  */
966fcf3ce44SJohn Forte void
isns_scn_callback(void * arg)967fcf3ce44SJohn Forte isns_scn_callback(void *arg)
968fcf3ce44SJohn Forte {
969fcf3ce44SJohn Forte 	int				i, pg_sz;
970fcf3ce44SJohn Forte 	int				qry_status;
971fcf3ce44SJohn Forte 	isns_portal_group_list_t	*pg_list;
972fcf3ce44SJohn Forte 	uint32_t			scn_type;
973fcf3ce44SJohn Forte 	iscsi_hba_t			*ihp;
974fcf3ce44SJohn Forte 
975fcf3ce44SJohn Forte 	if (arg == NULL) {
976fcf3ce44SJohn Forte 		/* No argument */
977fcf3ce44SJohn Forte 		return;
978fcf3ce44SJohn Forte 	}
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 	if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
9814246c8e9SJack Meng 		kmem_free(arg, sizeof (isns_scn_callback_arg_t));
9824246c8e9SJack Meng 		return;
9834246c8e9SJack Meng 	}
9844246c8e9SJack Meng 
9854246c8e9SJack Meng 	/*
9864246c8e9SJack Meng 	 * All isns callbacks are from a standalone taskq
9874246c8e9SJack Meng 	 * therefore the blocking here doesn't affect the enable/disable
9884246c8e9SJack Meng 	 * of isns discovery method
9894246c8e9SJack Meng 	 */
9904246c8e9SJack Meng 	if (iscsi_client_request_service(ihp) == B_FALSE) {
9914246c8e9SJack Meng 		kmem_free(arg, sizeof (isns_scn_callback_arg_t));
992fcf3ce44SJohn Forte 		return;
993fcf3ce44SJohn Forte 	}
994fcf3ce44SJohn Forte 
995fcf3ce44SJohn Forte 	scn_type = ((isns_scn_callback_arg_t *)arg)->scn_type;
996fcf3ce44SJohn Forte 	DTRACE_PROBE1(isns_scn_callback_scn_type, int, scn_type);
997fcf3ce44SJohn Forte 	switch (scn_type) {
998fcf3ce44SJohn Forte 	/*
999fcf3ce44SJohn Forte 	 * ISNS_OBJ_ADDED - An object has been added.
1000fcf3ce44SJohn Forte 	 */
1001fcf3ce44SJohn Forte 	case ISNS_OBJ_ADDED:
1002fcf3ce44SJohn Forte 		/* Query iSNS server for contact information */
1003fcf3ce44SJohn Forte 		pg_list = NULL;
1004fcf3ce44SJohn Forte 		qry_status = isns_query_one_node(
1005fcf3ce44SJohn Forte 		    ((isns_scn_callback_arg_t *)arg)->source_key_attr,
1006fcf3ce44SJohn Forte 		    ihp->hba_isid,
1007fcf3ce44SJohn Forte 		    ihp->hba_name,
1008fcf3ce44SJohn Forte 		    (uint8_t *)"",
1009fcf3ce44SJohn Forte 		    ISNS_INITIATOR_NODE_TYPE,
1010fcf3ce44SJohn Forte 		    &pg_list);
1011fcf3ce44SJohn Forte 
1012fcf3ce44SJohn Forte 		/* Verify portal group is found */
1013fcf3ce44SJohn Forte 		if ((qry_status != isns_ok &&
1014fcf3ce44SJohn Forte 		    qry_status != isns_op_partially_failed) ||
1015fcf3ce44SJohn Forte 		    pg_list == NULL) {
1016fcf3ce44SJohn Forte 			break;
1017fcf3ce44SJohn Forte 		}
1018fcf3ce44SJohn Forte 
1019fcf3ce44SJohn Forte 		DTRACE_PROBE1(pg_list,
1020fcf3ce44SJohn Forte 		    isns_portal_group_list_t *, pg_list);
1021fcf3ce44SJohn Forte 
1022fcf3ce44SJohn Forte 		/* Add all portals for logical unit to discovery cache */
1023fcf3ce44SJohn Forte 		for (i = 0; i < pg_list->pg_out_cnt; i++) {
1024fcf3ce44SJohn Forte 			iscsi_sockaddr_t addr_dsc;
1025fcf3ce44SJohn Forte 			iscsi_sockaddr_t addr_tgt;
1026fcf3ce44SJohn Forte 
1027fcf3ce44SJohn Forte 			iscsid_addr_to_sockaddr(
1028fcf3ce44SJohn Forte 			    pg_list->pg_list[i].isns_server_ip.i_insize,
1029fcf3ce44SJohn Forte 			    &pg_list->pg_list[i].isns_server_ip.i_addr,
1030fcf3ce44SJohn Forte 			    pg_list->pg_list[i].isns_server_port,
1031fcf3ce44SJohn Forte 			    &addr_dsc.sin);
1032fcf3ce44SJohn Forte 			iscsid_addr_to_sockaddr(pg_list->pg_list[i].insize,
1033fcf3ce44SJohn Forte 			    &pg_list->pg_list[i].pg_ip_addr,
1034fcf3ce44SJohn Forte 			    pg_list->pg_list[i].pg_port, &addr_tgt.sin);
1035fcf3ce44SJohn Forte 
1036fcf3ce44SJohn Forte 			(void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS,
1037fcf3ce44SJohn Forte 			    &addr_dsc.sin, (char *)pg_list->pg_list[i].
1038fcf3ce44SJohn Forte 			    pg_iscsi_name, pg_list->pg_list[i].pg_tag,
1039fcf3ce44SJohn Forte 			    &addr_tgt.sin);
1040fcf3ce44SJohn Forte 
1041fcf3ce44SJohn Forte 			/* Force target to login */
1042fcf3ce44SJohn Forte 			(void) iscsid_login_tgt(ihp, (char *)pg_list->
1043fcf3ce44SJohn Forte 			    pg_list[i].pg_iscsi_name, iSCSIDiscoveryMethodISNS,
1044fcf3ce44SJohn Forte 			    NULL);
1045fcf3ce44SJohn Forte 		}
1046fcf3ce44SJohn Forte 
1047fcf3ce44SJohn Forte 		if (pg_list != NULL) {
1048fcf3ce44SJohn Forte 			pg_sz = sizeof (isns_portal_group_list_t);
1049fcf3ce44SJohn Forte 			if (pg_list->pg_out_cnt > 0) {
1050fcf3ce44SJohn Forte 				pg_sz += (pg_list->pg_out_cnt - 1) *
1051fcf3ce44SJohn Forte 				    sizeof (isns_portal_group_t);
1052fcf3ce44SJohn Forte 			}
1053fcf3ce44SJohn Forte 			kmem_free(pg_list, pg_sz);
1054fcf3ce44SJohn Forte 		}
1055fcf3ce44SJohn Forte 		break;
1056fcf3ce44SJohn Forte 
1057fcf3ce44SJohn Forte 	/*
1058fcf3ce44SJohn Forte 	 * ISNS_OBJ_REMOVED - logical unit has been removed
1059fcf3ce44SJohn Forte 	 */
1060fcf3ce44SJohn Forte 	case ISNS_OBJ_REMOVED:
1061fcf3ce44SJohn Forte 		if (iscsid_del(ihp,
1062fcf3ce44SJohn Forte 		    (char *)((isns_scn_callback_arg_t *)arg)->
1063fcf3ce44SJohn Forte 		    source_key_attr, iSCSIDiscoveryMethodISNS, NULL) !=
1064fcf3ce44SJohn Forte 		    B_TRUE) {
1065fcf3ce44SJohn Forte 			cmn_err(CE_NOTE, "iscsi initiator - "
1066fcf3ce44SJohn Forte 			    "isns remove scn failed for target %s\n",
1067fcf3ce44SJohn Forte 			    (char *)((isns_scn_callback_arg_t *)arg)->
1068fcf3ce44SJohn Forte 			    source_key_attr);
1069fcf3ce44SJohn Forte 
1070fcf3ce44SJohn Forte 		}
1071fcf3ce44SJohn Forte 		break;
1072fcf3ce44SJohn Forte 
1073fcf3ce44SJohn Forte 	/*
1074fcf3ce44SJohn Forte 	 * ISNS_OBJ_UPDATED - logical unit has changed
1075fcf3ce44SJohn Forte 	 */
1076fcf3ce44SJohn Forte 	case ISNS_OBJ_UPDATED:
1077fcf3ce44SJohn Forte 		cmn_err(CE_NOTE, "iscsi initiator - "
1078fcf3ce44SJohn Forte 		    "received iSNS update SCN for %s\n",
1079fcf3ce44SJohn Forte 		    (char *)((isns_scn_callback_arg_t *)arg)->
1080fcf3ce44SJohn Forte 		    source_key_attr);
1081fcf3ce44SJohn Forte 		break;
1082fcf3ce44SJohn Forte 
1083fcf3ce44SJohn Forte 	/*
1084fcf3ce44SJohn Forte 	 * ISNS_OBJ_UNKNOWN -
1085fcf3ce44SJohn Forte 	 */
1086fcf3ce44SJohn Forte 	default:
1087fcf3ce44SJohn Forte 		cmn_err(CE_NOTE, "iscsi initiator - "
1088fcf3ce44SJohn Forte 		    "received unknown iSNS SCN type 0x%x\n", scn_type);
1089fcf3ce44SJohn Forte 		break;
1090fcf3ce44SJohn Forte 	}
1091fcf3ce44SJohn Forte 
10924246c8e9SJack Meng 	iscsi_client_release_service(ihp);
1093fcf3ce44SJohn Forte 	kmem_free(arg, sizeof (isns_scn_callback_arg_t));
1094fcf3ce44SJohn Forte }
1095fcf3ce44SJohn Forte 
1096fcf3ce44SJohn Forte 
1097fcf3ce44SJohn Forte /*
1098fcf3ce44SJohn Forte  * iscsid_add - Creates discovered session and connection
1099fcf3ce44SJohn Forte  */
1100fcf3ce44SJohn Forte static boolean_t
iscsid_add(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc,char * target_name,int tpgt,struct sockaddr * addr_tgt)1101fcf3ce44SJohn Forte iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
1102fcf3ce44SJohn Forte     struct sockaddr *addr_dsc, char *target_name, int tpgt,
1103fcf3ce44SJohn Forte     struct sockaddr *addr_tgt)
1104fcf3ce44SJohn Forte {
1105fcf3ce44SJohn Forte 	boolean_t	    rtn = B_TRUE;
1106fcf3ce44SJohn Forte 	iscsi_sess_t	    *isp;
1107fcf3ce44SJohn Forte 	iscsi_conn_t	    *icp;
1108fcf3ce44SJohn Forte 	uint_t		    oid;
1109fcf3ce44SJohn Forte 	int		    idx;
1110fcf3ce44SJohn Forte 	int		    isid;
1111fcf3ce44SJohn Forte 	iscsi_config_sess_t *ics;
1112fcf3ce44SJohn Forte 	int		    size;
1113fcf3ce44SJohn Forte 	char		    *tmp;
1114fcf3ce44SJohn Forte 
1115fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
1116fcf3ce44SJohn Forte 	ASSERT(addr_dsc != NULL);
1117fcf3ce44SJohn Forte 	ASSERT(target_name != NULL);
1118fcf3ce44SJohn Forte 	ASSERT(addr_tgt != NULL);
1119fcf3ce44SJohn Forte 
1120fcf3ce44SJohn Forte 	/* setup initial buffer for configured session information */
1121fcf3ce44SJohn Forte 	size = sizeof (*ics);
1122fcf3ce44SJohn Forte 	ics = kmem_zalloc(size, KM_SLEEP);
1123fcf3ce44SJohn Forte 	ics->ics_in = 1;
1124fcf3ce44SJohn Forte 
1125fcf3ce44SJohn Forte 	/* get configured sessions information */
1126fcf3ce44SJohn Forte 	tmp = target_name;
1127fcf3ce44SJohn Forte 	if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1128fcf3ce44SJohn Forte 		/*
1129fcf3ce44SJohn Forte 		 * No target information available check for
1130fcf3ce44SJohn Forte 		 * initiator information.
1131fcf3ce44SJohn Forte 		 */
1132fcf3ce44SJohn Forte 		tmp = (char *)ihp->hba_name;
1133fcf3ce44SJohn Forte 		if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1134fcf3ce44SJohn Forte 			/*
1135fcf3ce44SJohn Forte 			 * No hba information is
1136fcf3ce44SJohn Forte 			 * found.  So assume default
1137fcf3ce44SJohn Forte 			 * one session unbound behavior.
1138fcf3ce44SJohn Forte 			 */
1139fcf3ce44SJohn Forte 			ics->ics_out = 1;
1140fcf3ce44SJohn Forte 			ics->ics_bound = B_TRUE;
1141fcf3ce44SJohn Forte 		}
1142fcf3ce44SJohn Forte 	}
1143fcf3ce44SJohn Forte 
11446cefaae1SJack Meng 	if (iscsiboot_prop && (ics->ics_out > 1) &&
11456cefaae1SJack Meng 	    !iscsi_chk_bootlun_mpxio(ihp)) {
11466cefaae1SJack Meng 		/*
11476cefaae1SJack Meng 		 * iscsi boot with mpxio disabled
11486cefaae1SJack Meng 		 * no need to search configured boot session
11496cefaae1SJack Meng 		 */
11506cefaae1SJack Meng 
11516cefaae1SJack Meng 		if (iscsi_cmp_boot_ini_name(tmp) ||
11526cefaae1SJack Meng 		    iscsi_cmp_boot_tgt_name(tmp)) {
11536cefaae1SJack Meng 			ics->ics_out = 1;
11546cefaae1SJack Meng 			ics->ics_bound = B_FALSE;
11556cefaae1SJack Meng 		}
11566cefaae1SJack Meng 	}
1157fcf3ce44SJohn Forte 	/* Check to see if we need to get more information */
1158fcf3ce44SJohn Forte 	if (ics->ics_out > 1) {
1159fcf3ce44SJohn Forte 		/* record new size and free last buffer */
1160fcf3ce44SJohn Forte 		idx = ics->ics_out;
1161fcf3ce44SJohn Forte 		size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
1162fcf3ce44SJohn Forte 		kmem_free(ics, sizeof (*ics));
1163fcf3ce44SJohn Forte 
1164fcf3ce44SJohn Forte 		/* allocate new buffer */
1165fcf3ce44SJohn Forte 		ics = kmem_zalloc(size, KM_SLEEP);
1166fcf3ce44SJohn Forte 		ics->ics_in = idx;
1167fcf3ce44SJohn Forte 
1168fcf3ce44SJohn Forte 		/* get configured sessions information */
1169fcf3ce44SJohn Forte 		if (persistent_get_config_session(tmp, ics) != B_TRUE) {
1170fcf3ce44SJohn Forte 			cmn_err(CE_NOTE, "iscsi session(%s) - "
1171fcf3ce44SJohn Forte 			    "unable to get configured session information\n",
1172fcf3ce44SJohn Forte 			    target_name);
1173fcf3ce44SJohn Forte 			kmem_free(ics, size);
1174fcf3ce44SJohn Forte 			return (B_FALSE);
1175fcf3ce44SJohn Forte 		}
1176fcf3ce44SJohn Forte 	}
1177fcf3ce44SJohn Forte 
1178fcf3ce44SJohn Forte 	/* loop for all configured sessions */
1179fcf3ce44SJohn Forte 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1180fcf3ce44SJohn Forte 	for (isid = 0; isid < ics->ics_out; isid++) {
1181fcf3ce44SJohn Forte 		/* create or find matching session */
1182fcf3ce44SJohn Forte 		isp = iscsi_sess_create(ihp, method, addr_dsc, target_name,
1183fcf3ce44SJohn Forte 		    tpgt, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
1184fcf3ce44SJohn Forte 		if (isp == NULL) {
1185fcf3ce44SJohn Forte 			rtn = B_FALSE;
1186fcf3ce44SJohn Forte 			break;
1187fcf3ce44SJohn Forte 		}
1188fcf3ce44SJohn Forte 
1189fcf3ce44SJohn Forte 		/* create or find matching connection */
1190fcf3ce44SJohn Forte 		if (!ISCSI_SUCCESS(iscsi_conn_create(addr_tgt, isp, &icp))) {
119130e7468fSPeter Dunlap 			/*
119230e7468fSPeter Dunlap 			 * Teardown the session we just created.  It can't
119330e7468fSPeter Dunlap 			 * have any luns or connections associated with it
119430e7468fSPeter Dunlap 			 * so this should always succeed (luckily since what
119530e7468fSPeter Dunlap 			 * would we do if it failed?)
119630e7468fSPeter Dunlap 			 */
119730e7468fSPeter Dunlap 			(void) iscsi_sess_destroy(isp);
1198fcf3ce44SJohn Forte 			rtn = B_FALSE;
1199fcf3ce44SJohn Forte 			break;
1200fcf3ce44SJohn Forte 		}
1201fcf3ce44SJohn Forte 	}
1202fcf3ce44SJohn Forte 	rw_exit(&ihp->hba_sess_list_rwlock);
1203fcf3ce44SJohn Forte 	kmem_free(ics, size);
1204fcf3ce44SJohn Forte 	return (rtn);
1205fcf3ce44SJohn Forte }
1206fcf3ce44SJohn Forte 
1207fcf3ce44SJohn Forte /*
1208fcf3ce44SJohn Forte  * iscsid_del - Attempts to delete all associated sessions
1209fcf3ce44SJohn Forte  */
1210fcf3ce44SJohn Forte boolean_t
iscsid_del(iscsi_hba_t * ihp,char * target_name,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc)1211fcf3ce44SJohn Forte iscsid_del(iscsi_hba_t *ihp, char *target_name,
1212fcf3ce44SJohn Forte     iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1213fcf3ce44SJohn Forte {
1214fcf3ce44SJohn Forte 	boolean_t	rtn = B_TRUE;
1215fcf3ce44SJohn Forte 	iscsi_status_t	status;
1216fcf3ce44SJohn Forte 	iscsi_sess_t	*isp;
1217fcf3ce44SJohn Forte 	char		name[ISCSI_MAX_NAME_LEN];
1218fcf3ce44SJohn Forte 
1219fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
1220fcf3ce44SJohn Forte 	/* target name can be NULL or !NULL */
1221fcf3ce44SJohn Forte 	/* addr_dsc can be NULL or !NULL */
1222fcf3ce44SJohn Forte 
1223fcf3ce44SJohn Forte 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1224fcf3ce44SJohn Forte 	isp = ihp->hba_sess_list;
1225fcf3ce44SJohn Forte 	while (isp != NULL) {
1226fcf3ce44SJohn Forte 		/*
1227fcf3ce44SJohn Forte 		 * If no target_name is listed (meaning all targets)
1228fcf3ce44SJohn Forte 		 * or this specific target was listed. And the same
1229fcf3ce44SJohn Forte 		 * discovery method discovered this target then
1230fcf3ce44SJohn Forte 		 * continue evaulation.  Otherwise fail.
1231fcf3ce44SJohn Forte 		 */
1232fcf3ce44SJohn Forte 		if (((target_name == NULL) ||
1233fcf3ce44SJohn Forte 		    (strcmp((char *)isp->sess_name, target_name) == 0)) &&
1234fcf3ce44SJohn Forte 		    (isp->sess_discovered_by == method)) {
1235fcf3ce44SJohn Forte 			boolean_t try_destroy;
1236fcf3ce44SJohn Forte 
1237fcf3ce44SJohn Forte 			/*
1238fcf3ce44SJohn Forte 			 * If iSNS, SendTargets, or Static then special
1239fcf3ce44SJohn Forte 			 * handling for disc_addr.
1240fcf3ce44SJohn Forte 			 */
1241fcf3ce44SJohn Forte 			if ((method == iSCSIDiscoveryMethodISNS) ||
1242fcf3ce44SJohn Forte 			    (method == iSCSIDiscoveryMethodSendTargets)) {
1243fcf3ce44SJohn Forte 				/*
1244fcf3ce44SJohn Forte 				 * If NULL addr_dsc (meaning all disc_addr)
1245fcf3ce44SJohn Forte 				 * or matching discovered addr.
1246fcf3ce44SJohn Forte 				 */
1247fcf3ce44SJohn Forte 				if ((addr_dsc == NULL) ||
1248fcf3ce44SJohn Forte 				    (bcmp(addr_dsc, &isp->sess_discovered_addr,
1249fcf3ce44SJohn Forte 				    SIZEOF_SOCKADDR(
1250fcf3ce44SJohn Forte 				    &isp->sess_discovered_addr.sin)) == 0)) {
1251fcf3ce44SJohn Forte 					try_destroy = B_TRUE;
1252fcf3ce44SJohn Forte 				} else {
1253fcf3ce44SJohn Forte 					try_destroy = B_FALSE;
1254fcf3ce44SJohn Forte 				}
1255fcf3ce44SJohn Forte 			} else if (method == iSCSIDiscoveryMethodStatic) {
1256fcf3ce44SJohn Forte 				/*
1257fcf3ce44SJohn Forte 				 * If NULL addr_dsc (meaning all disc_addr)
1258fcf3ce44SJohn Forte 				 * or matching active connection.
1259fcf3ce44SJohn Forte 				 */
1260fcf3ce44SJohn Forte 				if ((addr_dsc == NULL) ||
1261fcf3ce44SJohn Forte 				    ((isp->sess_conn_act != NULL) &&
1262fcf3ce44SJohn Forte 				    (bcmp(addr_dsc,
1263fcf3ce44SJohn Forte 				    &isp->sess_conn_act->conn_base_addr.sin,
1264fcf3ce44SJohn Forte 				    SIZEOF_SOCKADDR(
1265fcf3ce44SJohn Forte 				    &isp->sess_conn_act->conn_base_addr.sin))
1266fcf3ce44SJohn Forte 				    == 0))) {
1267fcf3ce44SJohn Forte 					try_destroy = B_TRUE;
1268fcf3ce44SJohn Forte 				} else {
1269fcf3ce44SJohn Forte 					try_destroy = B_FALSE;
1270fcf3ce44SJohn Forte 				}
1271fcf3ce44SJohn Forte 			} else {
1272fcf3ce44SJohn Forte 				/* Unknown discovery specified */
1273fcf3ce44SJohn Forte 				try_destroy = B_TRUE;
1274fcf3ce44SJohn Forte 			}
1275fcf3ce44SJohn Forte 
12766cefaae1SJack Meng 			if (try_destroy == B_TRUE &&
12776cefaae1SJack Meng 			    isp->sess_boot == B_FALSE) {
1278fcf3ce44SJohn Forte 				(void) strcpy(name, (char *)isp->sess_name);
1279fcf3ce44SJohn Forte 				status = iscsi_sess_destroy(isp);
1280fcf3ce44SJohn Forte 				if (ISCSI_SUCCESS(status)) {
1281fcf3ce44SJohn Forte 					iscsid_remove_target_param(name);
1282fcf3ce44SJohn Forte 					isp = ihp->hba_sess_list;
12835295a27aSJack Meng 				} else if (status == ISCSI_STATUS_BUSY) {
1284fcf3ce44SJohn Forte 					/*
1285fcf3ce44SJohn Forte 					 * The most likely destroy failure
1286fcf3ce44SJohn Forte 					 * is that ndi/mdi offline failed.
1287fcf3ce44SJohn Forte 					 * This means that the resource is
1288fcf3ce44SJohn Forte 					 * in_use/busy.
1289fcf3ce44SJohn Forte 					 */
12905295a27aSJack Meng 					cmn_err(CE_NOTE, "iscsi session(%d) - "
12915295a27aSJack Meng 					    "resource is in use\n",
12925295a27aSJack Meng 					    isp->sess_oid);
12935295a27aSJack Meng 					isp = isp->sess_next;
12945295a27aSJack Meng 					rtn = B_FALSE;
12955295a27aSJack Meng 				} else {
1296fcf3ce44SJohn Forte 					cmn_err(CE_NOTE, "iscsi session(%d) - "
1297fcf3ce44SJohn Forte 					    "session logout failed (%d)\n",
1298fcf3ce44SJohn Forte 					    isp->sess_oid, status);
1299fcf3ce44SJohn Forte 					isp = isp->sess_next;
1300fcf3ce44SJohn Forte 					rtn = B_FALSE;
1301fcf3ce44SJohn Forte 				}
1302fcf3ce44SJohn Forte 			} else {
1303fcf3ce44SJohn Forte 				isp = isp->sess_next;
1304fcf3ce44SJohn Forte 			}
1305fcf3ce44SJohn Forte 		} else {
1306fcf3ce44SJohn Forte 			isp = isp->sess_next;
1307fcf3ce44SJohn Forte 		}
1308fcf3ce44SJohn Forte 	}
1309fcf3ce44SJohn Forte 	rw_exit(&ihp->hba_sess_list_rwlock);
1310fcf3ce44SJohn Forte 	return (rtn);
1311fcf3ce44SJohn Forte }
1312fcf3ce44SJohn Forte 
1313fcf3ce44SJohn Forte 
1314fcf3ce44SJohn Forte /*
1315fcf3ce44SJohn Forte  * iscsid_login_tgt - request target(s) to login
1316fcf3ce44SJohn Forte  */
1317fcf3ce44SJohn Forte boolean_t
iscsid_login_tgt(iscsi_hba_t * ihp,char * target_name,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc)1318fcf3ce44SJohn Forte iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
1319fcf3ce44SJohn Forte     iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1320fcf3ce44SJohn Forte {
1321a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	boolean_t		rtn		= B_FALSE;
1322a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	iscsi_sess_t		*isp		= NULL;
1323a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	iscsi_sess_list_t	*isp_list	= NULL;
1324a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	iscsi_sess_list_t	*last_sess	= NULL;
1325a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	iscsi_sess_list_t	*cur_sess	= NULL;
1326a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	int			total		= 0;
1327a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	ddi_taskq_t		*login_taskq	= NULL;
1328a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	char			taskq_name[ISCSI_TH_MAX_NAME_LEN] = {0};
1329a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	time_t			time_stamp;
1330fcf3ce44SJohn Forte 
1331fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
1332fcf3ce44SJohn Forte 
1333fcf3ce44SJohn Forte 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1334fcf3ce44SJohn Forte 	/* Loop thru sessions */
1335fcf3ce44SJohn Forte 	isp = ihp->hba_sess_list;
1336fcf3ce44SJohn Forte 	while (isp != NULL) {
1337fcf3ce44SJohn Forte 		boolean_t try_online;
13386cefaae1SJack Meng 		if (!(method & iSCSIDiscoveryMethodBoot)) {
13396cefaae1SJack Meng 			if (target_name == NULL) {
13406cefaae1SJack Meng 				if (method == iSCSIDiscoveryMethodUnknown) {
13416cefaae1SJack Meng 					/* unknown method mean login to all */
13426cefaae1SJack Meng 					try_online = B_TRUE;
13436cefaae1SJack Meng 				} else if (isp->sess_discovered_by & method) {
13446cefaae1SJack Meng 					if ((method ==
13456cefaae1SJack Meng 					    iSCSIDiscoveryMethodISNS) ||
13466cefaae1SJack Meng 					    (method ==
13476cefaae1SJack Meng 					    iSCSIDiscoveryMethodSendTargets)) {
13486cefaae1SJack Meng #define	SESS_DISC_ADDR	isp->sess_discovered_addr.sin
13496cefaae1SJack Meng 						if ((addr_dsc == NULL) ||
13506cefaae1SJack Meng 						    (bcmp(
13516cefaae1SJack Meng 						    &isp->sess_discovered_addr,
13526cefaae1SJack Meng 						    addr_dsc, SIZEOF_SOCKADDR(
13536cefaae1SJack Meng 						    &SESS_DISC_ADDR))
13546cefaae1SJack Meng 						    == 0)) {
13556cefaae1SJack Meng 							/*
13566cefaae1SJack Meng 							 * iSNS or sendtarget
13576cefaae1SJack Meng 							 * discovery and
13586cefaae1SJack Meng 							 * discovery address
13596cefaae1SJack Meng 							 * is NULL or match
13606cefaae1SJack Meng 							 */
13616cefaae1SJack Meng 							try_online = B_TRUE;
13626cefaae1SJack Meng 						} else {
1363fcf3ce44SJohn Forte 						/* addr_dsc not a match */
13646cefaae1SJack Meng 							try_online = B_FALSE;
13656cefaae1SJack Meng 						}
13666cefaae1SJack Meng #undef SESS_DISC_ADDR
13676cefaae1SJack Meng 					} else {
13686cefaae1SJack Meng 						/* static configuration */
13696cefaae1SJack Meng 						try_online = B_TRUE;
1370fcf3ce44SJohn Forte 					}
1371fcf3ce44SJohn Forte 				} else {
13726cefaae1SJack Meng 					/* method not a match */
13736cefaae1SJack Meng 					try_online = B_FALSE;
1374fcf3ce44SJohn Forte 				}
13756cefaae1SJack Meng 			} else if (strcmp(target_name,
13766cefaae1SJack Meng 			    (char *)isp->sess_name) == 0) {
13776cefaae1SJack Meng 				/* target_name match */
13786cefaae1SJack Meng 				try_online = B_TRUE;
1379fcf3ce44SJohn Forte 			} else {
13806cefaae1SJack Meng 				/* target_name not a match */
1381fcf3ce44SJohn Forte 				try_online = B_FALSE;
1382fcf3ce44SJohn Forte 			}
1383fcf3ce44SJohn Forte 		} else {
13846cefaae1SJack Meng 			/*
13856cefaae1SJack Meng 			 * online the boot session.
13866cefaae1SJack Meng 			 */
13876cefaae1SJack Meng 			if (isp->sess_boot == B_TRUE) {
13886cefaae1SJack Meng 				try_online = B_TRUE;
13896cefaae1SJack Meng 			}
1390fcf3ce44SJohn Forte 		}
1391fcf3ce44SJohn Forte 
1392a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		if (try_online == B_TRUE &&
1393a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		    isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1394a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			total++;
1395a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			/* Copy these sessions to the list. */
1396a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			if (isp_list == NULL) {
1397a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				isp_list =
1398a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    (iscsi_sess_list_t *)kmem_zalloc(
1399a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    sizeof (iscsi_sess_list_t), KM_SLEEP);
1400a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess = isp_list;
1401a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess->session = isp;
1402a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess->next = NULL;
1403a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			} else {
1404a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess->next =
1405a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    (iscsi_sess_list_t *)kmem_zalloc(
1406a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    sizeof (iscsi_sess_list_t), KM_SLEEP);
1407a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess->next->session = isp;
1408a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess->next->next = NULL;
1409a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				last_sess = last_sess->next;
1410a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			}
1411fcf3ce44SJohn Forte 			rtn = B_TRUE;
1412fcf3ce44SJohn Forte 		}
1413a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1414fcf3ce44SJohn Forte 		isp = isp->sess_next;
1415fcf3ce44SJohn Forte 	}
1416a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1417a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	if (total > 0) {
1418a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		time_stamp = ddi_get_time();
1419a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		(void) snprintf(taskq_name, (ISCSI_TH_MAX_NAME_LEN - 1),
1420a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		    "login_queue.%lx", time_stamp);
1421a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1422a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		login_taskq = ddi_taskq_create(ihp->hba_dip,
1423a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		    taskq_name, total, TASKQ_DEFAULTPRI, 0);
1424a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		if (login_taskq == NULL) {
1425a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			while (isp_list != NULL) {
1426a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				cur_sess = isp_list;
1427a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				isp_list = isp_list->next;
1428a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1429a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			}
1430a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			rtn = B_FALSE;
1431a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			rw_exit(&ihp->hba_sess_list_rwlock);
1432a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			return (rtn);
1433a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		}
1434a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1435a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		for (cur_sess = isp_list; cur_sess != NULL;
1436a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		    cur_sess = cur_sess->next) {
1437a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			if (ddi_taskq_dispatch(login_taskq,
1438a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			    iscsi_sess_online, (void *)cur_sess->session,
1439a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			    DDI_SLEEP) != DDI_SUCCESS) {
1440a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				cmn_err(CE_NOTE, "Can't dispatch the task "
1441a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    "for login to the target: %s",
1442a9ccff55Sbing zhao - Sun Microsystems - Beijing China 				    cur_sess->session->sess_name);
1443a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			}
1444a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		}
1445a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1446a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		ddi_taskq_wait(login_taskq);
1447a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		ddi_taskq_destroy(login_taskq);
1448a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		while (isp_list != NULL) {
1449a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			cur_sess = isp_list;
1450a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			isp_list = isp_list->next;
1451a9ccff55Sbing zhao - Sun Microsystems - Beijing China 			kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1452a9ccff55Sbing zhao - Sun Microsystems - Beijing China 		}
1453a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1454a9ccff55Sbing zhao - Sun Microsystems - Beijing China 	}
1455a9ccff55Sbing zhao - Sun Microsystems - Beijing China 
1456fcf3ce44SJohn Forte 	rw_exit(&ihp->hba_sess_list_rwlock);
1457fcf3ce44SJohn Forte 	return (rtn);
1458fcf3ce44SJohn Forte }
1459fcf3ce44SJohn Forte 
1460fcf3ce44SJohn Forte /*
1461fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
1462fcf3ce44SJohn Forte  * | Local Helper Functions                                             |
1463fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
1464fcf3ce44SJohn Forte  */
1465fcf3ce44SJohn Forte 
1466fcf3ce44SJohn Forte /*
1467fcf3ce44SJohn Forte  * iscsid_init_config -- initialize configuration parameters of iSCSI initiator
1468fcf3ce44SJohn Forte  */
1469fcf3ce44SJohn Forte static boolean_t
iscsid_init_config(iscsi_hba_t * ihp)1470fcf3ce44SJohn Forte iscsid_init_config(iscsi_hba_t *ihp)
1471fcf3ce44SJohn Forte {
1472fcf3ce44SJohn Forte 	iscsi_param_set_t	ips;
1473fcf3ce44SJohn Forte 	void *v = NULL;
1474fcf3ce44SJohn Forte 	char *name;
1475fcf3ce44SJohn Forte 	char *initiatorName;
1476fcf3ce44SJohn Forte 	persistent_param_t	pp;
1477aff4bce5Syi zhang - Sun Microsystems - Beijing China 	persistent_tunable_param_t pparam;
1478fcf3ce44SJohn Forte 	uint32_t		param_id;
1479fcf3ce44SJohn Forte 	int			rc;
1480fcf3ce44SJohn Forte 
1481fcf3ce44SJohn Forte 	/* allocate memory to hold initiator names */
1482fcf3ce44SJohn Forte 	initiatorName = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1483fcf3ce44SJohn Forte 
1484fcf3ce44SJohn Forte 	/*
1485fcf3ce44SJohn Forte 	 * initialize iSCSI initiator name
1486fcf3ce44SJohn Forte 	 */
1487fcf3ce44SJohn Forte 	bzero(&ips, sizeof (ips));
1488fcf3ce44SJohn Forte 	if (persistent_initiator_name_get(initiatorName,
1489fcf3ce44SJohn Forte 	    ISCSI_MAX_NAME_LEN) == B_TRUE) {
1490fcf3ce44SJohn Forte 		ips.s_vers	= ISCSI_INTERFACE_VERSION;
1491fcf3ce44SJohn Forte 		ips.s_param	= ISCSI_LOGIN_PARAM_INITIATOR_NAME;
1492fcf3ce44SJohn Forte 
14936cefaae1SJack Meng 		if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) {
14946cefaae1SJack Meng 			(void) strncpy(initiatorName,
14956cefaae1SJack Meng 			    (const char *)iscsiboot_prop->boot_init.ini_name,
14966cefaae1SJack Meng 			    ISCSI_MAX_NAME_LEN);
14976cefaae1SJack Meng 			(void) strncpy((char *)ips.s_value.v_name,
14986cefaae1SJack Meng 			    (const char *)iscsiboot_prop->boot_init.ini_name,
14996cefaae1SJack Meng 			    sizeof (ips.s_value.v_name));
15006cefaae1SJack Meng 			(void) iscsi_set_params(&ips, ihp, B_TRUE);
1501aff4bce5Syi zhang - Sun Microsystems - Beijing China 			/* use default tunable value */
1502aff4bce5Syi zhang - Sun Microsystems - Beijing China 			ihp->hba_tunable_params.recv_login_rsp_timeout =
1503aff4bce5Syi zhang - Sun Microsystems - Beijing China 			    ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1504aff4bce5Syi zhang - Sun Microsystems - Beijing China 			ihp->hba_tunable_params.polling_login_delay =
1505aff4bce5Syi zhang - Sun Microsystems - Beijing China 			    ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1506aff4bce5Syi zhang - Sun Microsystems - Beijing China 			ihp->hba_tunable_params.conn_login_max =
1507aff4bce5Syi zhang - Sun Microsystems - Beijing China 			    ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
15086cefaae1SJack Meng 			cmn_err(CE_NOTE, "Set initiator's name"
15096cefaae1SJack Meng 			    " from firmware");
15106cefaae1SJack Meng 		} else {
15116cefaae1SJack Meng 			(void) strncpy((char *)ips.s_value.v_name,
15126cefaae1SJack Meng 			    initiatorName, sizeof (ips.s_value.v_name));
15136cefaae1SJack Meng 
15146cefaae1SJack Meng 			(void) iscsi_set_params(&ips, ihp, B_FALSE);
1515aff4bce5Syi zhang - Sun Microsystems - Beijing China 			if (persistent_get_tunable_param(initiatorName,
1516aff4bce5Syi zhang - Sun Microsystems - Beijing China 			    &pparam) == B_FALSE) {
1517aff4bce5Syi zhang - Sun Microsystems - Beijing China 				/* use default value */
1518aff4bce5Syi zhang - Sun Microsystems - Beijing China 				pparam.p_params.recv_login_rsp_timeout =
1519aff4bce5Syi zhang - Sun Microsystems - Beijing China 				    ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1520aff4bce5Syi zhang - Sun Microsystems - Beijing China 				pparam.p_params.polling_login_delay =
1521aff4bce5Syi zhang - Sun Microsystems - Beijing China 				    ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1522aff4bce5Syi zhang - Sun Microsystems - Beijing China 				pparam.p_params.conn_login_max =
1523aff4bce5Syi zhang - Sun Microsystems - Beijing China 				    ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
1524aff4bce5Syi zhang - Sun Microsystems - Beijing China 			}
1525aff4bce5Syi zhang - Sun Microsystems - Beijing China 			bcopy(&pparam.p_params, &ihp->hba_tunable_params,
1526aff4bce5Syi zhang - Sun Microsystems - Beijing China 			    sizeof (iscsi_tunable_params_t));
15276cefaae1SJack Meng 		}
1528fcf3ce44SJohn Forte 	} else {
1529fcf3ce44SJohn Forte 		/*
15306cefaae1SJack Meng 		 * if no initiator-node name available it is most
15316cefaae1SJack Meng 		 * likely due to a fresh install, or the persistent
15326cefaae1SJack Meng 		 * store is not working correctly. Set
15336cefaae1SJack Meng 		 * a default initiator name so that the initiator can
1534fcf3ce44SJohn Forte 		 * be brought up properly.
1535fcf3ce44SJohn Forte 		 */
1536329c9e3dSJack Meng 		iscsid_set_default_initiator_node_settings(ihp, B_FALSE);
15376cefaae1SJack Meng 		(void) strncpy(initiatorName, (const char *)ihp->hba_name,
15386cefaae1SJack Meng 		    ISCSI_MAX_NAME_LEN);
1539fcf3ce44SJohn Forte 	}
1540fcf3ce44SJohn Forte 
1541fcf3ce44SJohn Forte 	/*
1542fcf3ce44SJohn Forte 	 * initialize iSCSI initiator alias (if any)
1543fcf3ce44SJohn Forte 	 */
1544fcf3ce44SJohn Forte 	bzero(&ips, sizeof (ips));
1545fcf3ce44SJohn Forte 	if (persistent_alias_name_get((char *)ips.s_value.v_name,
1546fcf3ce44SJohn Forte 	    sizeof (ips.s_value.v_name)) == B_TRUE) {
1547fcf3ce44SJohn Forte 		ips.s_param	= ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
1548fcf3ce44SJohn Forte 		(void) iscsi_set_params(&ips, ihp, B_FALSE);
1549fcf3ce44SJohn Forte 	} else {
1550fcf3ce44SJohn Forte 		/* EMPTY */
1551fcf3ce44SJohn Forte 		/* No alias defined - not a problem. */
1552fcf3ce44SJohn Forte 	}
1553fcf3ce44SJohn Forte 
1554fcf3ce44SJohn Forte 	/*
1555fcf3ce44SJohn Forte 	 * load up the overriden iSCSI initiator parameters
1556fcf3ce44SJohn Forte 	 */
1557fcf3ce44SJohn Forte 	name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1558fcf3ce44SJohn Forte 	persistent_param_lock();
1559fcf3ce44SJohn Forte 	v = NULL;
1560fcf3ce44SJohn Forte 	while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1561fcf3ce44SJohn Forte 		if (strncmp(name, initiatorName, ISCSI_MAX_NAME_LEN) == 0) {
1562fcf3ce44SJohn Forte 			ips.s_oid = ihp->hba_oid;
1563fcf3ce44SJohn Forte 			ips.s_vers = ISCSI_INTERFACE_VERSION;
1564fcf3ce44SJohn Forte 			for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1565fcf3ce44SJohn Forte 			    param_id++) {
1566fcf3ce44SJohn Forte 				if (pp.p_bitmap & (1 << param_id)) {
1567fcf3ce44SJohn Forte 					rc = iscsid_copyto_param_set(param_id,
1568fcf3ce44SJohn Forte 					    &pp.p_params, &ips);
1569fcf3ce44SJohn Forte 					if (rc == 0) {
1570fcf3ce44SJohn Forte 						rc = iscsi_set_params(&ips,
1571fcf3ce44SJohn Forte 						    ihp, B_FALSE);
1572fcf3ce44SJohn Forte 					}
1573fcf3ce44SJohn Forte 					if (rc != 0) {
1574fcf3ce44SJohn Forte 						/* note error but continue  */
1575fcf3ce44SJohn Forte 						cmn_err(CE_NOTE,
1576fcf3ce44SJohn Forte 						    "Failed to set "
1577fcf3ce44SJohn Forte 						    "param %d for OID %d",
1578fcf3ce44SJohn Forte 						    ips.s_param, ips.s_oid);
1579fcf3ce44SJohn Forte 					}
1580fcf3ce44SJohn Forte 				}
1581fcf3ce44SJohn Forte 			} /* END for() */
15826cefaae1SJack Meng 			if (iscsiboot_prop &&
15836cefaae1SJack Meng 			    iscsi_chk_bootlun_mpxio(ihp)) {
15846cefaae1SJack Meng 				(void) iscsi_reconfig_boot_sess(ihp);
15856cefaae1SJack Meng 			}
1586fcf3ce44SJohn Forte 			break;
1587fcf3ce44SJohn Forte 		}
1588fcf3ce44SJohn Forte 	} /* END while() */
1589fcf3ce44SJohn Forte 	persistent_param_unlock();
1590fcf3ce44SJohn Forte 
1591fcf3ce44SJohn Forte 	kmem_free(initiatorName, ISCSI_MAX_NAME_LEN);
1592fcf3ce44SJohn Forte 	kmem_free(name, ISCSI_MAX_NAME_LEN);
1593fcf3ce44SJohn Forte 	return (B_TRUE);
1594fcf3ce44SJohn Forte }
1595fcf3ce44SJohn Forte 
1596fcf3ce44SJohn Forte 
1597fcf3ce44SJohn Forte /*
1598fcf3ce44SJohn Forte  * iscsid_init_targets -- Load up the driver with known static targets and
1599fcf3ce44SJohn Forte  * targets whose parameters have been modified.
1600fcf3ce44SJohn Forte  *
1601fcf3ce44SJohn Forte  * This is done so that the CLI can find a list of targets the driver
1602fcf3ce44SJohn Forte  * currently knows about.
1603fcf3ce44SJohn Forte  *
1604fcf3ce44SJohn Forte  * The driver doesn't need to log into these targets.  Log in is done based
1605fcf3ce44SJohn Forte  * upon the enabled discovery methods.
1606fcf3ce44SJohn Forte  */
1607fcf3ce44SJohn Forte static boolean_t
iscsid_init_targets(iscsi_hba_t * ihp)1608fcf3ce44SJohn Forte iscsid_init_targets(iscsi_hba_t *ihp)
1609fcf3ce44SJohn Forte {
1610fcf3ce44SJohn Forte 	void			*v = NULL;
1611fcf3ce44SJohn Forte 	char			*name;
1612fcf3ce44SJohn Forte 	iscsi_param_set_t	ips;
1613fcf3ce44SJohn Forte 	persistent_param_t	pp;
1614fcf3ce44SJohn Forte 	char			*iname;
1615fcf3ce44SJohn Forte 	uint32_t		param_id;
1616fcf3ce44SJohn Forte 	int			rc;
1617fcf3ce44SJohn Forte 
1618fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
1619fcf3ce44SJohn Forte 
1620fcf3ce44SJohn Forte 	/* allocate memory to hold target names */
1621fcf3ce44SJohn Forte 	name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1622fcf3ce44SJohn Forte 
1623fcf3ce44SJohn Forte 	/*
1624fcf3ce44SJohn Forte 	 * load up targets whose parameters have been overriden
1625fcf3ce44SJohn Forte 	 */
1626fcf3ce44SJohn Forte 
1627fcf3ce44SJohn Forte 	/* ---- only need to be set once ---- */
1628fcf3ce44SJohn Forte 	bzero(&ips, sizeof (ips));
1629fcf3ce44SJohn Forte 	ips.s_vers = ISCSI_INTERFACE_VERSION;
1630fcf3ce44SJohn Forte 
1631fcf3ce44SJohn Forte 	/* allocate memory to hold initiator name */
1632fcf3ce44SJohn Forte 	iname = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1633fcf3ce44SJohn Forte 	(void) persistent_initiator_name_get(iname, ISCSI_MAX_NAME_LEN);
1634fcf3ce44SJohn Forte 
1635fcf3ce44SJohn Forte 	persistent_param_lock();
1636fcf3ce44SJohn Forte 	v = NULL;
1637fcf3ce44SJohn Forte 	while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1638fcf3ce44SJohn Forte 
1639fcf3ce44SJohn Forte 		if (strncmp(iname, name, ISCSI_MAX_NAME_LEN) == 0) {
1640fcf3ce44SJohn Forte 			/*
1641fcf3ce44SJohn Forte 			 * target name matched initiator's name so,
1642fcf3ce44SJohn Forte 			 * continue to next target.  Initiator's
1643fcf3ce44SJohn Forte 			 * parmeters have already been set.
1644fcf3ce44SJohn Forte 			 */
1645fcf3ce44SJohn Forte 			continue;
1646fcf3ce44SJohn Forte 		}
1647fcf3ce44SJohn Forte 
16486cefaae1SJack Meng 		if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
16496cefaae1SJack Meng 		    !iscsi_chk_bootlun_mpxio(ihp)) {
16506cefaae1SJack Meng 			/*
16516cefaae1SJack Meng 			 * boot target is not mpxio enabled
16526cefaae1SJack Meng 			 * simply ignore these overriden parameters
16536cefaae1SJack Meng 			 */
16546cefaae1SJack Meng 			continue;
16556cefaae1SJack Meng 		}
16566cefaae1SJack Meng 
1657fcf3ce44SJohn Forte 		ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name);
1658fcf3ce44SJohn Forte 
1659fcf3ce44SJohn Forte 		for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1660fcf3ce44SJohn Forte 		    param_id++) {
1661fcf3ce44SJohn Forte 			if (pp.p_bitmap & (1 << param_id)) {
1662fcf3ce44SJohn Forte 				rc = iscsid_copyto_param_set(param_id,
1663fcf3ce44SJohn Forte 				    &pp.p_params, &ips);
1664fcf3ce44SJohn Forte 				if (rc == 0) {
1665fcf3ce44SJohn Forte 					rc = iscsi_set_params(&ips,
1666fcf3ce44SJohn Forte 					    ihp, B_FALSE);
1667fcf3ce44SJohn Forte 				}
1668fcf3ce44SJohn Forte 				if (rc != 0) {
1669fcf3ce44SJohn Forte 					/* note error but continue  ---- */
1670fcf3ce44SJohn Forte 					cmn_err(CE_NOTE, "Failed to set "
1671fcf3ce44SJohn Forte 					    "param %d for OID %d",
1672fcf3ce44SJohn Forte 					    ips.s_param, ips.s_oid);
1673fcf3ce44SJohn Forte 				}
1674fcf3ce44SJohn Forte 			}
1675fcf3ce44SJohn Forte 		} /* END for() */
16766cefaae1SJack Meng 		if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
16776cefaae1SJack Meng 		    iscsi_chk_bootlun_mpxio(ihp)) {
16786cefaae1SJack Meng 			(void) iscsi_reconfig_boot_sess(ihp);
16796cefaae1SJack Meng 		}
1680fcf3ce44SJohn Forte 	} /* END while() */
1681fcf3ce44SJohn Forte 	persistent_param_unlock();
1682fcf3ce44SJohn Forte 
1683fcf3ce44SJohn Forte 	kmem_free(iname, ISCSI_MAX_NAME_LEN);
1684fcf3ce44SJohn Forte 	kmem_free(name, ISCSI_MAX_NAME_LEN);
1685fcf3ce44SJohn Forte 
1686fcf3ce44SJohn Forte 	return (B_TRUE);
1687fcf3ce44SJohn Forte }
1688fcf3ce44SJohn Forte 
1689fcf3ce44SJohn Forte 
1690fcf3ce44SJohn Forte /*
1691fcf3ce44SJohn Forte  * iscsid_thread_static -- If static discovery is enabled, this routine obtains
1692fcf3ce44SJohn Forte  * all statically configured targets from the peristent store and issues a
1693fcf3ce44SJohn Forte  * login request to the driver.
1694fcf3ce44SJohn Forte  */
1695fcf3ce44SJohn Forte /* ARGSUSED */
1696fcf3ce44SJohn Forte static void
iscsid_thread_static(iscsi_thread_t * thread,void * p)1697fcf3ce44SJohn Forte iscsid_thread_static(iscsi_thread_t *thread, void *p)
1698fcf3ce44SJohn Forte {
1699fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t	dm;
1700fcf3ce44SJohn Forte 	entry_t			entry;
1701fcf3ce44SJohn Forte 	char			name[ISCSI_MAX_NAME_LEN];
1702fcf3ce44SJohn Forte 	void			*v = NULL;
1703fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp = (iscsi_hba_t *)p;
1704fcf3ce44SJohn Forte 
1705fcf3ce44SJohn Forte 	while (iscsi_thread_wait(thread, -1) != 0) {
1706fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_TRUE);
1707fcf3ce44SJohn Forte 
1708fcf3ce44SJohn Forte 		/* ---- ensure static target discovery is enabled ---- */
1709fcf3ce44SJohn Forte 		dm = persistent_disc_meth_get();
1710fcf3ce44SJohn Forte 		if ((dm & iSCSIDiscoveryMethodStatic) == 0) {
1711fcf3ce44SJohn Forte 			cmn_err(CE_NOTE,
1712fcf3ce44SJohn Forte 			    "iscsi discovery failure - "
1713fcf3ce44SJohn Forte 			    "StaticTargets method is not enabled");
1714fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp,
1715fcf3ce44SJohn Forte 			    iSCSIDiscoveryMethodStatic, B_FALSE);
1716fcf3ce44SJohn Forte 			continue;
1717fcf3ce44SJohn Forte 		}
1718fcf3ce44SJohn Forte 
1719fcf3ce44SJohn Forte 		/*
1720fcf3ce44SJohn Forte 		 * walk list of the statically configured targets from the
1721fcf3ce44SJohn Forte 		 * persistent store
1722fcf3ce44SJohn Forte 		 */
1723fcf3ce44SJohn Forte 		v = NULL;
1724fcf3ce44SJohn Forte 		persistent_static_addr_lock();
1725fcf3ce44SJohn Forte 		while (persistent_static_addr_next(&v, name, &entry) ==
1726fcf3ce44SJohn Forte 		    B_TRUE) {
1727fcf3ce44SJohn Forte 			iscsi_sockaddr_t addr;
1728fcf3ce44SJohn Forte 
1729fcf3ce44SJohn Forte 			iscsid_addr_to_sockaddr(entry.e_insize,
1730fcf3ce44SJohn Forte 			    &(entry.e_u), entry.e_port, &addr.sin);
1731fcf3ce44SJohn Forte 
1732fcf3ce44SJohn Forte 			(void) iscsid_add(ihp, iSCSIDiscoveryMethodStatic,
1733fcf3ce44SJohn Forte 			    &addr.sin, name, entry.e_tpgt, &addr.sin);
1734fcf3ce44SJohn Forte 		}
1735fcf3ce44SJohn Forte 		persistent_static_addr_unlock();
1736fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_FALSE);
1737fcf3ce44SJohn Forte 	}
1738fcf3ce44SJohn Forte }
1739fcf3ce44SJohn Forte 
1740fcf3ce44SJohn Forte 
1741fcf3ce44SJohn Forte /*
1742fcf3ce44SJohn Forte  * iscsid_thread_sendtgts -- If SendTargets discovery is enabled, this routine
1743fcf3ce44SJohn Forte  * obtains all target discovery addresses configured from the peristent store
1744fcf3ce44SJohn Forte  * and probe the IP/port addresses for possible targets.  It will then issue
1745fcf3ce44SJohn Forte  * a login request to the driver for all discoveryed targets.
1746fcf3ce44SJohn Forte  */
1747fcf3ce44SJohn Forte static void
iscsid_thread_sendtgts(iscsi_thread_t * thread,void * p)1748fcf3ce44SJohn Forte iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p)
1749fcf3ce44SJohn Forte {
1750fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp = (iscsi_hba_t *)p;
1751fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t	dm;
1752fcf3ce44SJohn Forte 	entry_t			entry;
1753fcf3ce44SJohn Forte 	void			*v = NULL;
1754fcf3ce44SJohn Forte 
1755fcf3ce44SJohn Forte 	while (iscsi_thread_wait(thread, -1) != 0) {
1756fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1757fcf3ce44SJohn Forte 		    B_TRUE);
1758fcf3ce44SJohn Forte 
1759fcf3ce44SJohn Forte 		/* ---- ensure SendTargets discovery is enabled ---- */
1760fcf3ce44SJohn Forte 		dm = persistent_disc_meth_get();
1761fcf3ce44SJohn Forte 		if ((dm & iSCSIDiscoveryMethodSendTargets) == 0) {
1762fcf3ce44SJohn Forte 			cmn_err(CE_NOTE,
1763fcf3ce44SJohn Forte 			    "iscsi discovery failure - "
1764fcf3ce44SJohn Forte 			    "SendTargets method is not enabled");
1765fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp,
1766fcf3ce44SJohn Forte 			    iSCSIDiscoveryMethodSendTargets, B_FALSE);
1767fcf3ce44SJohn Forte 			continue;
1768fcf3ce44SJohn Forte 		}
1769fcf3ce44SJohn Forte 		/*
1770fcf3ce44SJohn Forte 		 * walk list of the SendTarget discovery addresses from the
1771fcf3ce44SJohn Forte 		 * persistent store
1772fcf3ce44SJohn Forte 		 */
1773fcf3ce44SJohn Forte 		v = NULL;
1774fcf3ce44SJohn Forte 		persistent_disc_addr_lock();
1775fcf3ce44SJohn Forte 		while (persistent_disc_addr_next(&v, &entry) == B_TRUE) {
1776fcf3ce44SJohn Forte 			iscsid_do_sendtgts(&entry);
1777fcf3ce44SJohn Forte 		}
1778fcf3ce44SJohn Forte 		persistent_disc_addr_unlock();
1779fcf3ce44SJohn Forte 
1780fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1781fcf3ce44SJohn Forte 		    B_FALSE);
1782fcf3ce44SJohn Forte 	}
1783fcf3ce44SJohn Forte }
1784fcf3ce44SJohn Forte 
1785fcf3ce44SJohn Forte /*
1786fcf3ce44SJohn Forte  * iscsid_thread_slp -- If SLP discovery is enabled,  this routine provides
1787fcf3ce44SJohn Forte  * the SLP discovery service.
1788fcf3ce44SJohn Forte  */
1789fcf3ce44SJohn Forte static void
iscsid_thread_slp(iscsi_thread_t * thread,void * p)1790fcf3ce44SJohn Forte iscsid_thread_slp(iscsi_thread_t *thread, void *p)
1791fcf3ce44SJohn Forte {
1792fcf3ce44SJohn Forte 	iscsi_hba_t  *ihp = (iscsi_hba_t *)p;
1793fcf3ce44SJohn Forte 
1794fcf3ce44SJohn Forte 	do {
1795fcf3ce44SJohn Forte 		/*
1796fcf3ce44SJohn Forte 		 * Even though we don't have support for SLP at this point
1797fcf3ce44SJohn Forte 		 * we'll send the events if someone has enabled this thread.
1798fcf3ce44SJohn Forte 		 * If this is not done the daemon waiting for discovery to
1799fcf3ce44SJohn Forte 		 * complete will pause forever holding up the boot process.
1800fcf3ce44SJohn Forte 		 */
1801fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_TRUE);
1802fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_FALSE);
1803fcf3ce44SJohn Forte 	} while (iscsi_thread_wait(thread, -1) != 0);
1804fcf3ce44SJohn Forte }
1805fcf3ce44SJohn Forte 
1806fcf3ce44SJohn Forte /*
1807fcf3ce44SJohn Forte  * iscsid_thread_isns --
1808fcf3ce44SJohn Forte  */
1809fcf3ce44SJohn Forte static void
iscsid_thread_isns(iscsi_thread_t * thread,void * ptr)1810fcf3ce44SJohn Forte iscsid_thread_isns(iscsi_thread_t *thread, void *ptr)
1811fcf3ce44SJohn Forte {
1812fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp = (iscsi_hba_t *)ptr;
1813fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t	dm;
1814fcf3ce44SJohn Forte 
1815fcf3ce44SJohn Forte 	while (iscsi_thread_wait(thread, -1) != 0) {
1816fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_TRUE);
1817fcf3ce44SJohn Forte 
1818fcf3ce44SJohn Forte 		/* ---- ensure iSNS discovery is enabled ---- */
1819fcf3ce44SJohn Forte 		dm = persistent_disc_meth_get();
1820fcf3ce44SJohn Forte 		if ((dm & iSCSIDiscoveryMethodISNS) == 0) {
1821fcf3ce44SJohn Forte 			cmn_err(CE_NOTE,
1822fcf3ce44SJohn Forte 			    "iscsi discovery failure - "
1823fcf3ce44SJohn Forte 			    "iSNS method is not enabled");
1824fcf3ce44SJohn Forte 			iscsi_discovery_event(ihp,
1825fcf3ce44SJohn Forte 			    iSCSIDiscoveryMethodISNS, B_FALSE);
1826fcf3ce44SJohn Forte 			continue;
1827fcf3ce44SJohn Forte 		}
1828fcf3ce44SJohn Forte 
1829fcf3ce44SJohn Forte 		(void) isns_reg(ihp->hba_isid,
1830fcf3ce44SJohn Forte 		    ihp->hba_name,
1831fcf3ce44SJohn Forte 		    ISCSI_MAX_NAME_LEN,
1832fcf3ce44SJohn Forte 		    ihp->hba_alias,
1833fcf3ce44SJohn Forte 		    ISCSI_MAX_NAME_LEN,
1834fcf3ce44SJohn Forte 		    ISNS_INITIATOR_NODE_TYPE,
1835fcf3ce44SJohn Forte 		    isns_scn_callback);
1836fcf3ce44SJohn Forte 		iscsid_do_isns_query(ihp);
1837fcf3ce44SJohn Forte 		iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_FALSE);
1838fcf3ce44SJohn Forte 	}
1839fcf3ce44SJohn Forte 
1840fcf3ce44SJohn Forte 	/* Thread stopped. Deregister from iSNS servers(s). */
1841fcf3ce44SJohn Forte 	(void) isns_dereg(ihp->hba_isid, ihp->hba_name);
1842fcf3ce44SJohn Forte }
1843fcf3ce44SJohn Forte 
1844fcf3ce44SJohn Forte 
1845fcf3ce44SJohn Forte /*
1846fcf3ce44SJohn Forte  * iscsid_threads_create -- Creates all the discovery threads.
1847fcf3ce44SJohn Forte  */
1848fcf3ce44SJohn Forte static void
iscsid_threads_create(iscsi_hba_t * ihp)1849fcf3ce44SJohn Forte iscsid_threads_create(iscsi_hba_t *ihp)
1850fcf3ce44SJohn Forte {
1851fcf3ce44SJohn Forte 	iscsid_thr_table	*t;
1852fcf3ce44SJohn Forte 
1853fcf3ce44SJohn Forte 	/*
1854fcf3ce44SJohn Forte 	 * start a thread for each discovery method
1855fcf3ce44SJohn Forte 	 */
1856fcf3ce44SJohn Forte 	for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1857fcf3ce44SJohn Forte 	    t++) {
1858fcf3ce44SJohn Forte 		if (t->thr_id == NULL) {
1859fcf3ce44SJohn Forte 			t->thr_id = iscsi_thread_create(ihp->hba_dip, t->name,
1860fcf3ce44SJohn Forte 			    t->func_start, ihp);
1861fcf3ce44SJohn Forte 		}
1862fcf3ce44SJohn Forte 	}
1863fcf3ce44SJohn Forte }
1864fcf3ce44SJohn Forte 
1865fcf3ce44SJohn Forte /*
1866fcf3ce44SJohn Forte  * iscsid_threads_destroy -- Destroys all the discovery threads.
1867fcf3ce44SJohn Forte  */
1868fcf3ce44SJohn Forte static void
iscsid_threads_destroy(void)1869fcf3ce44SJohn Forte iscsid_threads_destroy(void)
1870fcf3ce44SJohn Forte {
1871fcf3ce44SJohn Forte 	iscsid_thr_table	*t;
1872fcf3ce44SJohn Forte 
1873fcf3ce44SJohn Forte 	for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1874fcf3ce44SJohn Forte 	    t++) {
1875fcf3ce44SJohn Forte 		if (t->thr_id != NULL) {
1876fcf3ce44SJohn Forte 			iscsi_thread_destroy(t->thr_id);
1877fcf3ce44SJohn Forte 			t->thr_id = NULL;
1878fcf3ce44SJohn Forte 		}
1879fcf3ce44SJohn Forte 	}
1880fcf3ce44SJohn Forte }
1881fcf3ce44SJohn Forte 
1882fcf3ce44SJohn Forte /*
1883fcf3ce44SJohn Forte  * iscsid_copyto_param_set - helper function for iscsid_init_params.
1884fcf3ce44SJohn Forte  */
1885fcf3ce44SJohn Forte static int
iscsid_copyto_param_set(uint32_t param_id,iscsi_login_params_t * params,iscsi_param_set_t * ipsp)1886fcf3ce44SJohn Forte iscsid_copyto_param_set(uint32_t param_id, iscsi_login_params_t *params,
1887fcf3ce44SJohn Forte     iscsi_param_set_t *ipsp)
1888fcf3ce44SJohn Forte {
1889fcf3ce44SJohn Forte 	int rtn = 0;
1890fcf3ce44SJohn Forte 
1891fcf3ce44SJohn Forte 	if (param_id >= ISCSI_NUM_LOGIN_PARAM) {
1892fcf3ce44SJohn Forte 		return (EINVAL);
1893fcf3ce44SJohn Forte 	}
1894fcf3ce44SJohn Forte 
1895fcf3ce44SJohn Forte 	switch (param_id) {
1896fcf3ce44SJohn Forte 
1897fcf3ce44SJohn Forte 	/*
1898fcf3ce44SJohn Forte 	 * Boolean parameters
1899fcf3ce44SJohn Forte 	 */
1900fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER:
1901fcf3ce44SJohn Forte 		ipsp->s_value.v_bool = params->data_pdu_in_order;
1902fcf3ce44SJohn Forte 		break;
1903fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA:
1904fcf3ce44SJohn Forte 		ipsp->s_value.v_bool = params->immediate_data;
1905fcf3ce44SJohn Forte 		break;
1906fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_INITIAL_R2T:
1907fcf3ce44SJohn Forte 		ipsp->s_value.v_bool = params->initial_r2t;
1908fcf3ce44SJohn Forte 		break;
1909fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER:
1910fcf3ce44SJohn Forte 		ipsp->s_value.v_bool = params->data_pdu_in_order;
1911fcf3ce44SJohn Forte 		break;
1912fcf3ce44SJohn Forte 
1913fcf3ce44SJohn Forte 	/*
1914fcf3ce44SJohn Forte 	 * Integer parameters
1915fcf3ce44SJohn Forte 	 */
1916fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_HEADER_DIGEST:
1917fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->header_digest;
1918fcf3ce44SJohn Forte 		break;
1919fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_DATA_DIGEST:
1920fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->data_digest;
1921fcf3ce44SJohn Forte 		break;
1922fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN:
1923fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->default_time_to_retain;
1924fcf3ce44SJohn Forte 		break;
1925fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT:
1926fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->default_time_to_wait;
1927fcf3ce44SJohn Forte 		break;
1928fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH:
1929fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->max_recv_data_seg_len;
1930fcf3ce44SJohn Forte 		break;
1931fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH:
1932fcf3ce44SJohn Forte 		ipsp->s_value.v_integer = params->first_burst_length;
1933fcf3ce44SJohn Forte 		break;
1934fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH:
1935fcf3ce44SJohn Forte 		ipsp->s_value.v_integer =  params->max_burst_length;
1936fcf3ce44SJohn Forte 		break;
1937fcf3ce44SJohn Forte 
1938fcf3ce44SJohn Forte 	/*
1939fcf3ce44SJohn Forte 	 * Integer parameters which currently are unsettable
1940fcf3ce44SJohn Forte 	 */
1941fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS:
1942fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T:
1943fcf3ce44SJohn Forte 	case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL:
1944fcf3ce44SJohn Forte 	/* ---- drop through to default case ---- */
1945fcf3ce44SJohn Forte 	default:
1946fcf3ce44SJohn Forte 		rtn = EINVAL;
1947fcf3ce44SJohn Forte 		break;
1948fcf3ce44SJohn Forte 	}
1949fcf3ce44SJohn Forte 
1950fcf3ce44SJohn Forte 	/* if all is well, set the parameter identifier */
1951fcf3ce44SJohn Forte 	if (rtn == 0) {
1952fcf3ce44SJohn Forte 		ipsp->s_param = param_id;
1953fcf3ce44SJohn Forte 	}
1954fcf3ce44SJohn Forte 
1955fcf3ce44SJohn Forte 	return (rtn);
1956fcf3ce44SJohn Forte }
1957fcf3ce44SJohn Forte 
1958fcf3ce44SJohn Forte /*
1959fcf3ce44SJohn Forte  * iscsid_add_pg_list_to_cache - Add portal groups in the list to the
1960fcf3ce44SJohn Forte  * discovery cache.
1961fcf3ce44SJohn Forte  */
1962fcf3ce44SJohn Forte static void
iscsid_add_pg_list_to_cache(iscsi_hba_t * ihp,isns_portal_group_list_t * pg_list)1963fcf3ce44SJohn Forte iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
1964fcf3ce44SJohn Forte     isns_portal_group_list_t *pg_list)
1965fcf3ce44SJohn Forte {
1966fcf3ce44SJohn Forte 	int		    i;
1967fcf3ce44SJohn Forte 
1968fcf3ce44SJohn Forte 	for (i = 0; i < pg_list->pg_out_cnt; i++) {
1969fcf3ce44SJohn Forte 		iscsi_sockaddr_t addr_dsc;
1970fcf3ce44SJohn Forte 		iscsi_sockaddr_t addr_tgt;
1971fcf3ce44SJohn Forte 
1972fcf3ce44SJohn Forte 		iscsid_addr_to_sockaddr(
1973fcf3ce44SJohn Forte 		    pg_list->pg_list[i].isns_server_ip.i_insize,
1974fcf3ce44SJohn Forte 		    &pg_list->pg_list[i].isns_server_ip.i_addr,
1975fcf3ce44SJohn Forte 		    pg_list->pg_list[i].isns_server_port,
1976fcf3ce44SJohn Forte 		    &addr_dsc.sin);
1977fcf3ce44SJohn Forte 		iscsid_addr_to_sockaddr(
1978fcf3ce44SJohn Forte 		    pg_list->pg_list[i].insize,
1979fcf3ce44SJohn Forte 		    &pg_list->pg_list[i].pg_ip_addr,
1980fcf3ce44SJohn Forte 		    pg_list->pg_list[i].pg_port,
1981fcf3ce44SJohn Forte 		    &addr_tgt.sin);
1982fcf3ce44SJohn Forte 
1983fcf3ce44SJohn Forte 		(void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, &addr_dsc.sin,
1984fcf3ce44SJohn Forte 		    (char *)pg_list->pg_list[i].pg_iscsi_name,
1985fcf3ce44SJohn Forte 		    pg_list->pg_list[i].pg_tag, &addr_tgt.sin);
1986fcf3ce44SJohn Forte 	}
1987fcf3ce44SJohn Forte }
1988fcf3ce44SJohn Forte 
1989fcf3ce44SJohn Forte /*
1990fcf3ce44SJohn Forte  * set_initiator_name - set default initiator name and alias.
1991fcf3ce44SJohn Forte  *
1992fcf3ce44SJohn Forte  * This sets the default initiator name and alias.  The
1993fcf3ce44SJohn Forte  * initiator name is composed of sun's reverse domain name
1994fcf3ce44SJohn Forte  * and registration followed and a unique classifier.  This
1995fcf3ce44SJohn Forte  * classifier is the mac address of the first NIC in the
1996fcf3ce44SJohn Forte  * host and a timestamp to make sure the classifier is
1997fcf3ce44SJohn Forte  * unique if the NIC is moved between hosts.  The alias
1998fcf3ce44SJohn Forte  * is just the hostname.
1999fcf3ce44SJohn Forte  */
2000329c9e3dSJack Meng void
iscsid_set_default_initiator_node_settings(iscsi_hba_t * ihp,boolean_t minimal)2001329c9e3dSJack Meng iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp, boolean_t minimal)
2002fcf3ce44SJohn Forte {
2003fcf3ce44SJohn Forte 	int		    i;
2004fcf3ce44SJohn Forte 	time_t		    x;
2005fcf3ce44SJohn Forte 	struct ether_addr   eaddr;
2006fcf3ce44SJohn Forte 	char		    val[10];
2007fcf3ce44SJohn Forte 	iscsi_chap_props_t  *chap = NULL;
2008fcf3ce44SJohn Forte 
2009fcf3ce44SJohn Forte 	/* Set default initiator-node name */
20106cefaae1SJack Meng 	if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) {
20116cefaae1SJack Meng 		(void) strncpy((char *)ihp->hba_name,
20126cefaae1SJack Meng 		    (const char *)iscsiboot_prop->boot_init.ini_name,
20136cefaae1SJack Meng 		    ISCSI_MAX_NAME_LEN);
20146cefaae1SJack Meng 	} else {
20156cefaae1SJack Meng 		(void) snprintf((char *)ihp->hba_name,
20166cefaae1SJack Meng 		    ISCSI_MAX_NAME_LEN,
20176cefaae1SJack Meng 		    "iqn.1986-03.com.sun:01:");
20186cefaae1SJack Meng 
20196cefaae1SJack Meng 		(void) localetheraddr(NULL, &eaddr);
20206cefaae1SJack Meng 		for (i = 0; i <  ETHERADDRL; i++) {
20216cefaae1SJack Meng 			(void) snprintf(val, sizeof (val), "%02x",
20226cefaae1SJack Meng 			    eaddr.ether_addr_octet[i]);
20236cefaae1SJack Meng 			(void) strncat((char *)ihp->hba_name, val,
20246cefaae1SJack Meng 			    ISCSI_MAX_NAME_LEN);
20256cefaae1SJack Meng 		}
20266cefaae1SJack Meng 
20276cefaae1SJack Meng 		/* Set default initiator-node alias */
20286cefaae1SJack Meng 		x = ddi_get_time();
20296cefaae1SJack Meng 		(void) snprintf(val, sizeof (val), ".%lx", x);
2030fcf3ce44SJohn Forte 		(void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN);
2031fcf3ce44SJohn Forte 
20326cefaae1SJack Meng 		if (ihp->hba_alias[0] == '\0') {
20336cefaae1SJack Meng 			(void) strncpy((char *)ihp->hba_alias,
20346cefaae1SJack Meng 			    utsname.nodename, ISCSI_MAX_NAME_LEN);
20356cefaae1SJack Meng 			ihp->hba_alias_length = strlen((char *)ihp->hba_alias);
2036329c9e3dSJack Meng 			if (minimal == B_FALSE) {
2037329c9e3dSJack Meng 				(void) persistent_alias_name_set(
2038329c9e3dSJack Meng 				    (char *)ihp->hba_alias);
2039329c9e3dSJack Meng 			}
20406cefaae1SJack Meng 		}
2041fcf3ce44SJohn Forte 	}
2042329c9e3dSJack Meng 
2043329c9e3dSJack Meng 	if (minimal == B_TRUE) {
2044329c9e3dSJack Meng 		return;
2045329c9e3dSJack Meng 	}
2046329c9e3dSJack Meng 
20476cefaae1SJack Meng 	(void) persistent_initiator_name_set((char *)ihp->hba_name);
2048fcf3ce44SJohn Forte 
2049fcf3ce44SJohn Forte 	/* Set default initiator-node CHAP settings */
2050fcf3ce44SJohn Forte 	if (persistent_initiator_name_get((char *)ihp->hba_name,
2051fcf3ce44SJohn Forte 	    ISCSI_MAX_NAME_LEN) == B_TRUE) {
2052fcf3ce44SJohn Forte 		chap = (iscsi_chap_props_t *)kmem_zalloc(sizeof (*chap),
2053fcf3ce44SJohn Forte 		    KM_SLEEP);
2054fcf3ce44SJohn Forte 		if (persistent_chap_get((char *)ihp->hba_name, chap) ==
2055fcf3ce44SJohn Forte 		    B_FALSE) {
2056fcf3ce44SJohn Forte 			bcopy((char *)ihp->hba_name, chap->c_user,
2057fcf3ce44SJohn Forte 			    strlen((char *)ihp->hba_name));
2058fcf3ce44SJohn Forte 			chap->c_user_len = strlen((char *)ihp->hba_name);
2059fcf3ce44SJohn Forte 			(void) persistent_chap_set((char *)ihp->hba_name, chap);
2060fcf3ce44SJohn Forte 		}
2061fcf3ce44SJohn Forte 		kmem_free(chap, sizeof (*chap));
2062fcf3ce44SJohn Forte 	}
2063fcf3ce44SJohn Forte }
2064fcf3ce44SJohn Forte 
2065fcf3ce44SJohn Forte static void
iscsid_remove_target_param(char * name)2066fcf3ce44SJohn Forte iscsid_remove_target_param(char *name)
2067fcf3ce44SJohn Forte {
2068fcf3ce44SJohn Forte 	persistent_param_t  *pparam;
2069fcf3ce44SJohn Forte 	uint32_t	    t_oid;
2070fcf3ce44SJohn Forte 	iscsi_config_sess_t *ics;
2071fcf3ce44SJohn Forte 
2072fcf3ce44SJohn Forte 	ASSERT(name != NULL);
2073fcf3ce44SJohn Forte 
2074fcf3ce44SJohn Forte 	/*
2075fcf3ce44SJohn Forte 	 * Remove target-param <-> target mapping.
2076fcf3ce44SJohn Forte 	 * Only remove if there is not any overridden
2077fcf3ce44SJohn Forte 	 * parameters in the persistent store
2078fcf3ce44SJohn Forte 	 */
2079fcf3ce44SJohn Forte 	pparam = (persistent_param_t *)kmem_zalloc(sizeof (*pparam), KM_SLEEP);
2080fcf3ce44SJohn Forte 
2081fcf3ce44SJohn Forte 	/*
2082fcf3ce44SJohn Forte 	 * setup initial buffer for configured session
2083fcf3ce44SJohn Forte 	 * information
2084fcf3ce44SJohn Forte 	 */
2085fcf3ce44SJohn Forte 	ics = (iscsi_config_sess_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
2086fcf3ce44SJohn Forte 	ics->ics_in = 1;
2087fcf3ce44SJohn Forte 
2088fcf3ce44SJohn Forte 	if ((persistent_param_get(name, pparam) == B_FALSE) &&
2089fcf3ce44SJohn Forte 	    (persistent_get_config_session(name, ics) == B_FALSE))  {
2090fcf3ce44SJohn Forte 		t_oid = iscsi_targetparam_get_oid((uchar_t *)name);
2091fcf3ce44SJohn Forte 		(void) iscsi_targetparam_remove_target(t_oid);
2092fcf3ce44SJohn Forte 	}
2093fcf3ce44SJohn Forte 
2094fcf3ce44SJohn Forte 	kmem_free(pparam, sizeof (*pparam));
2095fcf3ce44SJohn Forte 	pparam = NULL;
2096fcf3ce44SJohn Forte 	kmem_free(ics, sizeof (*ics));
2097fcf3ce44SJohn Forte 	ics = NULL;
2098fcf3ce44SJohn Forte }
2099fcf3ce44SJohn Forte 
2100fcf3ce44SJohn Forte /*
2101fcf3ce44SJohn Forte  * iscsid_addr_to_sockaddr - convert other types to struct sockaddr
2102fcf3ce44SJohn Forte  */
2103fcf3ce44SJohn Forte void
iscsid_addr_to_sockaddr(int src_insize,void * src_addr,int src_port,struct sockaddr * dst_addr)2104fcf3ce44SJohn Forte iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port,
2105fcf3ce44SJohn Forte     struct sockaddr *dst_addr)
2106fcf3ce44SJohn Forte {
2107fcf3ce44SJohn Forte 	ASSERT((src_insize == sizeof (struct in_addr)) ||
2108fcf3ce44SJohn Forte 	    (src_insize == sizeof (struct in6_addr)));
2109fcf3ce44SJohn Forte 	ASSERT(src_addr != NULL);
2110fcf3ce44SJohn Forte 	ASSERT(dst_addr != NULL);
2111fcf3ce44SJohn Forte 
2112fcf3ce44SJohn Forte 	bzero(dst_addr, sizeof (*dst_addr));
2113fcf3ce44SJohn Forte 
2114fcf3ce44SJohn Forte 	/* translate discovery information */
2115fcf3ce44SJohn Forte 	if (src_insize == sizeof (struct in_addr)) {
2116fcf3ce44SJohn Forte 		struct sockaddr_in *addr_in =
2117fcf3ce44SJohn Forte 		    (struct sockaddr_in *)dst_addr;
2118fcf3ce44SJohn Forte 		addr_in->sin_family = AF_INET;
2119fcf3ce44SJohn Forte 		bcopy(src_addr, &addr_in->sin_addr.s_addr,
2120fcf3ce44SJohn Forte 		    sizeof (struct in_addr));
2121fcf3ce44SJohn Forte 		addr_in->sin_port = htons(src_port);
2122fcf3ce44SJohn Forte 	} else {
2123fcf3ce44SJohn Forte 		struct sockaddr_in6 *addr_in6 =
2124fcf3ce44SJohn Forte 		    (struct sockaddr_in6 *)dst_addr;
2125fcf3ce44SJohn Forte 		addr_in6->sin6_family = AF_INET6;
2126fcf3ce44SJohn Forte 		bcopy(src_addr, &addr_in6->sin6_addr.s6_addr,
2127fcf3ce44SJohn Forte 		    sizeof (struct in6_addr));
2128fcf3ce44SJohn Forte 		addr_in6->sin6_port = htons(src_port);
2129fcf3ce44SJohn Forte 	}
2130fcf3ce44SJohn Forte }
2131fcf3ce44SJohn Forte 
2132fcf3ce44SJohn Forte /*
2133fcf3ce44SJohn Forte  * iscsi_discovery_event -- send event associated with discovery operations
2134fcf3ce44SJohn Forte  *
2135fcf3ce44SJohn Forte  * Each discovery event has a start and end event. Which is sent is based
2136fcf3ce44SJohn Forte  * on the boolean argument start with the obvious results.
2137fcf3ce44SJohn Forte  */
2138fcf3ce44SJohn Forte static void
iscsi_discovery_event(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t m,boolean_t start)2139fcf3ce44SJohn Forte iscsi_discovery_event(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t m,
2140fcf3ce44SJohn Forte     boolean_t start)
2141fcf3ce44SJohn Forte {
2142fcf3ce44SJohn Forte 	char	*subclass = NULL;
2143fcf3ce44SJohn Forte 
2144fcf3ce44SJohn Forte 	mutex_enter(&ihp->hba_discovery_events_mutex);
2145fcf3ce44SJohn Forte 	switch (m) {
2146fcf3ce44SJohn Forte 	case iSCSIDiscoveryMethodStatic:
2147fcf3ce44SJohn Forte 		if (start == B_TRUE) {
2148fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_STATIC_START;
2149fcf3ce44SJohn Forte 		} else {
2150fcf3ce44SJohn Forte 			ihp->hba_discovery_events |= iSCSIDiscoveryMethodStatic;
2151fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_STATIC_END;
2152fcf3ce44SJohn Forte 		}
2153fcf3ce44SJohn Forte 		break;
2154fcf3ce44SJohn Forte 
2155fcf3ce44SJohn Forte 	case iSCSIDiscoveryMethodSendTargets:
2156fcf3ce44SJohn Forte 		if (start == B_TRUE) {
2157fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_SEND_TARGETS_START;
2158fcf3ce44SJohn Forte 		} else {
2159fcf3ce44SJohn Forte 			ihp->hba_discovery_events |=
2160fcf3ce44SJohn Forte 			    iSCSIDiscoveryMethodSendTargets;
2161fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_SEND_TARGETS_END;
2162fcf3ce44SJohn Forte 		}
2163fcf3ce44SJohn Forte 		break;
2164fcf3ce44SJohn Forte 
2165fcf3ce44SJohn Forte 	case iSCSIDiscoveryMethodSLP:
2166fcf3ce44SJohn Forte 		if (start == B_TRUE) {
2167fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_SLP_START;
2168fcf3ce44SJohn Forte 		} else {
2169fcf3ce44SJohn Forte 			ihp->hba_discovery_events |= iSCSIDiscoveryMethodSLP;
2170fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_SLP_END;
2171fcf3ce44SJohn Forte 		}
2172fcf3ce44SJohn Forte 		break;
2173fcf3ce44SJohn Forte 
2174fcf3ce44SJohn Forte 	case iSCSIDiscoveryMethodISNS:
2175fcf3ce44SJohn Forte 		if (start == B_TRUE) {
2176fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_ISNS_START;
2177fcf3ce44SJohn Forte 		} else {
2178fcf3ce44SJohn Forte 			ihp->hba_discovery_events |= iSCSIDiscoveryMethodISNS;
2179fcf3ce44SJohn Forte 			subclass = ESC_ISCSI_ISNS_END;
2180fcf3ce44SJohn Forte 		}
2181fcf3ce44SJohn Forte 		break;
2182fcf3ce44SJohn Forte 	}
2183fcf3ce44SJohn Forte 	mutex_exit(&ihp->hba_discovery_events_mutex);
2184c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	iscsi_send_sysevent(ihp, EC_ISCSI, subclass, NULL);
2185fcf3ce44SJohn Forte }
2186fcf3ce44SJohn Forte 
2187fcf3ce44SJohn Forte /*
2188c60a6da3Sbing zhao - Sun Microsystems - Beijing China  * iscsi_send_sysevent -- send sysevent using specified class
2189fcf3ce44SJohn Forte  */
2190c60a6da3Sbing zhao - Sun Microsystems - Beijing China void
iscsi_send_sysevent(iscsi_hba_t * ihp,char * eventclass,char * subclass,nvlist_t * np)2191c60a6da3Sbing zhao - Sun Microsystems - Beijing China iscsi_send_sysevent(
2192c60a6da3Sbing zhao - Sun Microsystems - Beijing China     iscsi_hba_t	*ihp,
2193c60a6da3Sbing zhao - Sun Microsystems - Beijing China     char	*eventclass,
2194c60a6da3Sbing zhao - Sun Microsystems - Beijing China     char	*subclass,
2195c60a6da3Sbing zhao - Sun Microsystems - Beijing China     nvlist_t	*np)
2196fcf3ce44SJohn Forte {
2197c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	(void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, eventclass,
2198fcf3ce44SJohn Forte 	    subclass, np, NULL, DDI_SLEEP);
2199fcf3ce44SJohn Forte }
22006cefaae1SJack Meng 
22016cefaae1SJack Meng static boolean_t
iscsid_boot_init_config(iscsi_hba_t * ihp)22026cefaae1SJack Meng iscsid_boot_init_config(iscsi_hba_t *ihp)
22036cefaae1SJack Meng {
22046cefaae1SJack Meng 	if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) {
22056cefaae1SJack Meng 		bcopy(iscsiboot_prop->boot_init.ini_name,
22066cefaae1SJack Meng 		    ihp->hba_name,
22076cefaae1SJack Meng 		    strlen((const char *)iscsiboot_prop->boot_init.ini_name));
22086cefaae1SJack Meng 	}
22096cefaae1SJack Meng 	/* or using default login param for boot session */
22106cefaae1SJack Meng 	return (B_TRUE);
22116cefaae1SJack Meng }
22126cefaae1SJack Meng 
22136cefaae1SJack Meng boolean_t
iscsi_reconfig_boot_sess(iscsi_hba_t * ihp)22146cefaae1SJack Meng iscsi_reconfig_boot_sess(iscsi_hba_t *ihp)
22156cefaae1SJack Meng {
22166cefaae1SJack Meng 	iscsi_config_sess_t	*ics;
22176cefaae1SJack Meng 	int			idx;
22186cefaae1SJack Meng 	iscsi_sess_t		*isp, *t_isp;
22196cefaae1SJack Meng 	int			isid, size;
22206cefaae1SJack Meng 	char			*name;
22216cefaae1SJack Meng 	boolean_t		rtn = B_TRUE;
2222904e51f6SJack Meng 	uint32_t		event_count;
22236cefaae1SJack Meng 
22246cefaae1SJack Meng 	if (iscsiboot_prop == NULL) {
22256cefaae1SJack Meng 		return (B_FALSE);
22266cefaae1SJack Meng 	}
22276cefaae1SJack Meng 	size = sizeof (*ics);
22286cefaae1SJack Meng 	ics = kmem_zalloc(size, KM_SLEEP);
22296cefaae1SJack Meng 	ics->ics_in = 1;
22306cefaae1SJack Meng 
22316cefaae1SJack Meng 	/* get information of number of sessions to be configured */
22326cefaae1SJack Meng 	name = (char *)iscsiboot_prop->boot_tgt.tgt_name;
22336cefaae1SJack Meng 	if (persistent_get_config_session(name, ics) == B_FALSE) {
22346cefaae1SJack Meng 		/*
22356cefaae1SJack Meng 		 * No target information available to check
22366cefaae1SJack Meng 		 * initiator information. Assume one session
22376cefaae1SJack Meng 		 * by default.
22386cefaae1SJack Meng 		 */
22396cefaae1SJack Meng 		name = (char *)iscsiboot_prop->boot_init.ini_name;
22406cefaae1SJack Meng 		if (persistent_get_config_session(name, ics) == B_FALSE) {
22416cefaae1SJack Meng 			ics->ics_out = 1;
22426cefaae1SJack Meng 			ics->ics_bound = B_TRUE;
22436cefaae1SJack Meng 		}
22446cefaae1SJack Meng 	}
22456cefaae1SJack Meng 
22466cefaae1SJack Meng 	/* get necessary information */
22476cefaae1SJack Meng 	if (ics->ics_out > 1) {
22486cefaae1SJack Meng 		idx = ics->ics_out;
22496cefaae1SJack Meng 		size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
22506cefaae1SJack Meng 		kmem_free(ics, sizeof (*ics));
22516cefaae1SJack Meng 
22526cefaae1SJack Meng 		ics = kmem_zalloc(size, KM_SLEEP);
22536cefaae1SJack Meng 		ics->ics_in = idx;
22546cefaae1SJack Meng 
22556cefaae1SJack Meng 		/* get configured sessions information */
22566cefaae1SJack Meng 		if (persistent_get_config_session((char *)name,
22576cefaae1SJack Meng 		    ics) != B_TRUE) {
22586cefaae1SJack Meng 			cmn_err(CE_NOTE, "session(%s) - "
22596cefaae1SJack Meng 			    "failed to setup multiple sessions",
22606cefaae1SJack Meng 			    name);
22616cefaae1SJack Meng 			kmem_free(ics, size);
22626cefaae1SJack Meng 			return (B_FALSE);
22636cefaae1SJack Meng 		}
22646cefaae1SJack Meng 	}
22656cefaae1SJack Meng 
22666cefaae1SJack Meng 	/* create a temporary session to keep boot session connective */
22676cefaae1SJack Meng 	t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS);
22686cefaae1SJack Meng 	if (t_isp == NULL) {
22696cefaae1SJack Meng 		cmn_err(CE_NOTE, "session(%s) - "
22706cefaae1SJack Meng 		    "failed to setup multiple sessions", name);
22716cefaae1SJack Meng 		rw_exit(&ihp->hba_sess_list_rwlock);
22726cefaae1SJack Meng 		kmem_free(ics, size);
22736cefaae1SJack Meng 		return (B_FALSE);
22746cefaae1SJack Meng 	}
22756cefaae1SJack Meng 
22766cefaae1SJack Meng 	/* destroy all old boot sessions */
22776cefaae1SJack Meng 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
22786cefaae1SJack Meng 	isp = ihp->hba_sess_list;
22796cefaae1SJack Meng 	while (isp != NULL) {
22806cefaae1SJack Meng 		if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
22816cefaae1SJack Meng 			if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) {
22826cefaae1SJack Meng 				/*
22836cefaae1SJack Meng 				 * destroy all stale sessions
22846cefaae1SJack Meng 				 * except temporary boot session
22856cefaae1SJack Meng 				 */
22866cefaae1SJack Meng 				if (ISCSI_SUCCESS(iscsi_sess_destroy(
22876cefaae1SJack Meng 				    isp))) {
22886cefaae1SJack Meng 					isp = ihp->hba_sess_list;
22896cefaae1SJack Meng 				} else {
22906cefaae1SJack Meng 					/*
22916cefaae1SJack Meng 					 * couldn't destroy stale sessions
22926cefaae1SJack Meng 					 * at least poke it to disconnect
22936cefaae1SJack Meng 					 */
2294904e51f6SJack Meng 					event_count = atomic_inc_32_nv(
2295904e51f6SJack Meng 					    &isp->sess_state_event_count);
2296904e51f6SJack Meng 					iscsi_sess_enter_state_zone(isp);
22976cefaae1SJack Meng 					iscsi_sess_state_machine(isp,
2298904e51f6SJack Meng 					    ISCSI_SESS_EVENT_N7, event_count);
2299904e51f6SJack Meng 					iscsi_sess_exit_state_zone(isp);
2300904e51f6SJack Meng 
23016cefaae1SJack Meng 					isp = isp->sess_next;
23026cefaae1SJack Meng 					cmn_err(CE_NOTE, "session(%s) - "
23036cefaae1SJack Meng 					    "failed to setup multiple"
23046cefaae1SJack Meng 					    " sessions", name);
23056cefaae1SJack Meng 				}
23066cefaae1SJack Meng 			} else {
23076cefaae1SJack Meng 				isp = isp->sess_next;
23086cefaae1SJack Meng 			}
23096cefaae1SJack Meng 		} else {
23106cefaae1SJack Meng 			isp = isp->sess_next;
23116cefaae1SJack Meng 		}
23126cefaae1SJack Meng 	}
23136cefaae1SJack Meng 	rw_exit(&ihp->hba_sess_list_rwlock);
23146cefaae1SJack Meng 
23156cefaae1SJack Meng 	for (isid = 0; isid < ics->ics_out; isid++) {
23166cefaae1SJack Meng 		isp = iscsi_add_boot_sess(ihp, isid);
23176cefaae1SJack Meng 		if (isp == NULL) {
23186cefaae1SJack Meng 			cmn_err(CE_NOTE, "session(%s) - failed to setup"
23196cefaae1SJack Meng 			    " multiple sessions", name);
23206cefaae1SJack Meng 			rtn = B_FALSE;
23216cefaae1SJack Meng 			break;
23226cefaae1SJack Meng 		}
23236cefaae1SJack Meng 	}
23246cefaae1SJack Meng 	if (!rtn && (isid == 0)) {
23256cefaae1SJack Meng 		/*
23266cefaae1SJack Meng 		 * fail to create any new boot session
23276cefaae1SJack Meng 		 * so only the temporary session is alive
23286cefaae1SJack Meng 		 * quit without destroying it
23296cefaae1SJack Meng 		 */
23306cefaae1SJack Meng 		kmem_free(ics, size);
23316cefaae1SJack Meng 		return (rtn);
23326cefaae1SJack Meng 	}
23336cefaae1SJack Meng 
23346cefaae1SJack Meng 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
23356cefaae1SJack Meng 	if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) {
23366cefaae1SJack Meng 		/* couldn't destroy temp boot session */
23376cefaae1SJack Meng 		cmn_err(CE_NOTE, "session(%s) - "
23386cefaae1SJack Meng 		    "failed to setup multiple sessions", name);
23396cefaae1SJack Meng 		rw_exit(&ihp->hba_sess_list_rwlock);
23406cefaae1SJack Meng 		rtn = B_FALSE;
23416cefaae1SJack Meng 	}
23426cefaae1SJack Meng 	rw_exit(&ihp->hba_sess_list_rwlock);
23436cefaae1SJack Meng 
23446cefaae1SJack Meng 	kmem_free(ics, size);
23456cefaae1SJack Meng 	return (rtn);
23466cefaae1SJack Meng }
23476cefaae1SJack Meng 
23486cefaae1SJack Meng static iscsi_sess_t *
iscsi_add_boot_sess(iscsi_hba_t * ihp,int isid)23496cefaae1SJack Meng iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid)
23506cefaae1SJack Meng {
23516cefaae1SJack Meng 	iscsi_sess_t	*isp;
23526cefaae1SJack Meng 	iscsi_conn_t    *icp;
23536cefaae1SJack Meng 	uint_t		oid;
23546cefaae1SJack Meng 
23556cefaae1SJack Meng 	iscsi_sockaddr_t	addr_dst;
23566cefaae1SJack Meng 
23576cefaae1SJack Meng 	addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family;
23586cefaae1SJack Meng 	if (addr_dst.sin.sa_family == AF_INET) {
23596cefaae1SJack Meng 		bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr,
23606cefaae1SJack Meng 		    &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr));
23616cefaae1SJack Meng 		addr_dst.sin4.sin_port =
23626cefaae1SJack Meng 		    htons(iscsiboot_prop->boot_tgt.tgt_port);
23636cefaae1SJack Meng 	} else {
23646cefaae1SJack Meng 		bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr,
23656cefaae1SJack Meng 		    &addr_dst.sin6.sin6_addr.s6_addr,
23666cefaae1SJack Meng 		    sizeof (struct in6_addr));
23676cefaae1SJack Meng 		addr_dst.sin6.sin6_port =
23686cefaae1SJack Meng 		    htons(iscsiboot_prop->boot_tgt.tgt_port);
23696cefaae1SJack Meng 	}
23706cefaae1SJack Meng 
23716cefaae1SJack Meng 	rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
23726cefaae1SJack Meng 	isp = iscsi_sess_create(ihp,
23736cefaae1SJack Meng 	    iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
23746cefaae1SJack Meng 	    (struct sockaddr *)&addr_dst,
23756cefaae1SJack Meng 	    (char *)iscsiboot_prop->boot_tgt.tgt_name,
23766cefaae1SJack Meng 	    ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
23776cefaae1SJack Meng 	if (isp == NULL) {
23786cefaae1SJack Meng 		/* create temp booting session failed */
23796cefaae1SJack Meng 		rw_exit(&ihp->hba_sess_list_rwlock);
23806cefaae1SJack Meng 		return (NULL);
23816cefaae1SJack Meng 	}
23826cefaae1SJack Meng 	isp->sess_boot = B_TRUE;
23836cefaae1SJack Meng 
23846cefaae1SJack Meng 	if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst,
23856cefaae1SJack Meng 	    isp, &icp))) {
23866cefaae1SJack Meng 		rw_exit(&ihp->hba_sess_list_rwlock);
23876cefaae1SJack Meng 		return (NULL);
23886cefaae1SJack Meng 	}
23896cefaae1SJack Meng 
23906cefaae1SJack Meng 	rw_exit(&ihp->hba_sess_list_rwlock);
23916cefaae1SJack Meng 	/* now online created session */
23926cefaae1SJack Meng 	if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name,
23936cefaae1SJack Meng 	    iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
23946cefaae1SJack Meng 	    (struct sockaddr *)&addr_dst) == B_FALSE) {
23956cefaae1SJack Meng 		return (NULL);
23966cefaae1SJack Meng 	}
23976cefaae1SJack Meng 
23986cefaae1SJack Meng 	return (isp);
23996cefaae1SJack Meng }
24006cefaae1SJack Meng 
24016cefaae1SJack Meng static void
iscsid_thread_boot_wd(iscsi_thread_t * thread,void * p)24026cefaae1SJack Meng iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p)
24036cefaae1SJack Meng {
24044246c8e9SJack Meng 	int			rc = 1;
24056cefaae1SJack Meng 	iscsi_hba_t		*ihp = (iscsi_hba_t *)p;
24064246c8e9SJack Meng 	boolean_t		reconfigured = B_FALSE;
24076cefaae1SJack Meng 
24086cefaae1SJack Meng 	while (rc != 0) {
24094246c8e9SJack Meng 		if (iscsiboot_prop && (modrootloaded == 1)) {
24104246c8e9SJack Meng 			if (ihp->hba_persistent_loaded == B_FALSE) {
24114246c8e9SJack Meng 				if (persistent_load() == B_TRUE) {
24124246c8e9SJack Meng 					ihp->hba_persistent_loaded = B_TRUE;
24134246c8e9SJack Meng 				}
24144246c8e9SJack Meng 			}
24154246c8e9SJack Meng 			if ((ihp->hba_persistent_loaded == B_TRUE) &&
24164246c8e9SJack Meng 			    (reconfigured == B_FALSE)) {
2417169c6dc4SJack Meng 				if (iscsi_chk_bootlun_mpxio(ihp) == B_TRUE) {
2418169c6dc4SJack Meng 					(void) iscsi_reconfig_boot_sess(ihp);
2419169c6dc4SJack Meng 					iscsid_poke_discovery(ihp,
2420169c6dc4SJack Meng 					    iSCSIDiscoveryMethodUnknown);
2421169c6dc4SJack Meng 					(void) iscsid_login_tgt(ihp, NULL,
2422169c6dc4SJack Meng 					    iSCSIDiscoveryMethodUnknown, NULL);
2423169c6dc4SJack Meng 				}
24244246c8e9SJack Meng 				reconfigured = B_TRUE;
24254246c8e9SJack Meng 			}
24266cefaae1SJack Meng 			break;
24276cefaae1SJack Meng 		}
24286cefaae1SJack Meng 		rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
24296cefaae1SJack Meng 	}
24306cefaae1SJack Meng }
24316cefaae1SJack Meng 
24326cefaae1SJack Meng boolean_t
iscsi_cmp_boot_tgt_name(char * name)24336cefaae1SJack Meng iscsi_cmp_boot_tgt_name(char *name)
24346cefaae1SJack Meng {
24356cefaae1SJack Meng 	if (iscsiboot_prop && (strncmp((const char *)name,
24366cefaae1SJack Meng 	    (const char *)iscsiboot_prop->boot_tgt.tgt_name,
24376cefaae1SJack Meng 	    ISCSI_MAX_NAME_LEN) == 0)) {
24386cefaae1SJack Meng 		return (B_TRUE);
24396cefaae1SJack Meng 	} else {
24406cefaae1SJack Meng 		return (B_FALSE);
24416cefaae1SJack Meng 	}
24426cefaae1SJack Meng }
24436cefaae1SJack Meng 
24446cefaae1SJack Meng boolean_t
iscsi_cmp_boot_ini_name(char * name)24456cefaae1SJack Meng iscsi_cmp_boot_ini_name(char *name)
24466cefaae1SJack Meng {
24476cefaae1SJack Meng 	if (iscsiboot_prop && (strncmp((const char *)name,
24486cefaae1SJack Meng 	    (const char *)iscsiboot_prop->boot_init.ini_name,
24496cefaae1SJack Meng 	    ISCSI_MAX_NAME_LEN) == 0)) {
24506cefaae1SJack Meng 		return (B_TRUE);
24516cefaae1SJack Meng 	} else {
24526cefaae1SJack Meng 		return (B_FALSE);
24536cefaae1SJack Meng 	}
24546cefaae1SJack Meng }
24556cefaae1SJack Meng 
24566cefaae1SJack Meng boolean_t
iscsi_chk_bootlun_mpxio(iscsi_hba_t * ihp)24576cefaae1SJack Meng iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp)
24586cefaae1SJack Meng {
24596cefaae1SJack Meng 	iscsi_sess_t    *isp;
24606cefaae1SJack Meng 	iscsi_lun_t	*ilp;
24616cefaae1SJack Meng 	isp = ihp->hba_sess_list;
24626cefaae1SJack Meng 	boolean_t	tgt_mpxio_enabled = B_FALSE;
24636cefaae1SJack Meng 	boolean_t	bootlun_found = B_FALSE;
24646cefaae1SJack Meng 	uint16_t    lun_num;
24656cefaae1SJack Meng 
24666cefaae1SJack Meng 	if (iscsiboot_prop == NULL) {
24676cefaae1SJack Meng 		return (B_FALSE);
24686cefaae1SJack Meng 	}
24696cefaae1SJack Meng 
24706cefaae1SJack Meng 	if (!ihp->hba_mpxio_enabled) {
24716cefaae1SJack Meng 		return (B_FALSE);
24726cefaae1SJack Meng 	}
24736cefaae1SJack Meng 
24746cefaae1SJack Meng 	lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun));
24756cefaae1SJack Meng 
24766cefaae1SJack Meng 	while (isp != NULL) {
24776cefaae1SJack Meng 		if ((strncmp((char *)isp->sess_name,
24786cefaae1SJack Meng 		    (const char *)iscsiboot_prop->boot_tgt.tgt_name,
24796cefaae1SJack Meng 		    ISCSI_MAX_NAME_LEN) == 0) &&
24806cefaae1SJack Meng 		    (isp->sess_boot == B_TRUE)) {
24816cefaae1SJack Meng 			/*
24826cefaae1SJack Meng 			 * found boot session.
24836cefaae1SJack Meng 			 * check its mdi path info is null or not
24846cefaae1SJack Meng 			 */
24856cefaae1SJack Meng 			ilp = isp->sess_lun_list;
24866cefaae1SJack Meng 			while (ilp != NULL) {
24876cefaae1SJack Meng 				if (lun_num == ilp->lun_num) {
24886cefaae1SJack Meng 					if (ilp->lun_pip) {
24896cefaae1SJack Meng 						tgt_mpxio_enabled = B_TRUE;
24906cefaae1SJack Meng 					}
24916cefaae1SJack Meng 					bootlun_found = B_TRUE;
24926cefaae1SJack Meng 				}
24936cefaae1SJack Meng 				ilp = ilp->lun_next;
24946cefaae1SJack Meng 			}
24956cefaae1SJack Meng 		}
24966cefaae1SJack Meng 		isp = isp->sess_next;
24976cefaae1SJack Meng 	}
24986cefaae1SJack Meng 	if (bootlun_found) {
24996cefaae1SJack Meng 		return (tgt_mpxio_enabled);
25006cefaae1SJack Meng 	} else {
25016cefaae1SJack Meng 		/*
25026cefaae1SJack Meng 		 * iscsiboot_prop not NULL while no boot lun found
25036cefaae1SJack Meng 		 * in most cases this is none iscsi boot while iscsiboot_prop
25046cefaae1SJack Meng 		 * is not NULL, in this scenario return iscsi HBA's mpxio config
25056cefaae1SJack Meng 		 */
25066cefaae1SJack Meng 		return (ihp->hba_mpxio_enabled);
25076cefaae1SJack Meng 	}
25086cefaae1SJack Meng }
2509f53e1f19SJack Meng 
2510f53e1f19SJack Meng static boolean_t
iscsid_check_active_boot_conn(iscsi_hba_t * ihp)2511f53e1f19SJack Meng iscsid_check_active_boot_conn(iscsi_hba_t *ihp)
2512f53e1f19SJack Meng {
2513f53e1f19SJack Meng 	iscsi_sess_t	*isp = NULL;
2514f53e1f19SJack Meng 	iscsi_conn_t	*icp = NULL;
2515f53e1f19SJack Meng 
2516f53e1f19SJack Meng 	rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
2517f53e1f19SJack Meng 	isp = ihp->hba_sess_list;
2518f53e1f19SJack Meng 	while (isp != NULL) {
2519f53e1f19SJack Meng 		if (isp->sess_boot == B_TRUE) {
2520f53e1f19SJack Meng 			rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2521f53e1f19SJack Meng 			icp = isp->sess_conn_list;
2522f53e1f19SJack Meng 			while (icp != NULL) {
2523f53e1f19SJack Meng 				if (icp->conn_state ==
2524f53e1f19SJack Meng 				    ISCSI_CONN_STATE_LOGGED_IN) {
2525f53e1f19SJack Meng 					rw_exit(&isp->sess_conn_list_rwlock);
2526f53e1f19SJack Meng 					rw_exit(&ihp->hba_sess_list_rwlock);
2527f53e1f19SJack Meng 					return (B_TRUE);
2528f53e1f19SJack Meng 				}
2529f53e1f19SJack Meng 				icp = icp->conn_next;
2530f53e1f19SJack Meng 			}
2531f53e1f19SJack Meng 			rw_exit(&isp->sess_conn_list_rwlock);
2532f53e1f19SJack Meng 		}
2533f53e1f19SJack Meng 		isp = isp->sess_next;
2534f53e1f19SJack Meng 	}
2535f53e1f19SJack Meng 	rw_exit(&ihp->hba_sess_list_rwlock);
2536f53e1f19SJack Meng 
2537f53e1f19SJack Meng 	return (B_FALSE);
2538f53e1f19SJack Meng }
2539