xref: /illumos-gate/usr/src/uts/common/io/comstar/port/iscsit/iscsit_isns.c (revision d656abb5804319b33c85955a73ee450ef7ff9739)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/cpuvar.h>
27 #include <sys/types.h>
28 #include <sys/conf.h>
29 #include <sys/file.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/socket.h>
33 #include <inet/tcp.h>
34 #include <sys/sdt.h>
35 
36 #include <sys/stmf.h>
37 #include <sys/stmf_ioctl.h>
38 #include <sys/portif.h>
39 #include <sys/idm/idm.h>
40 #include <sys/idm/idm_so.h>
41 #include <sys/iscsit/iscsit_common.h>
42 #include <sys/iscsit/isns_protocol.h>
43 #include <iscsit.h>
44 #include <iscsit_isns.h>
45 #include <sys/ksocket.h>
46 
47 /* local defines */
48 #define	MAX_XID			(2^16)
49 #define	ISNS_IDLE_TIME		60
50 #define	MAX_RETRY		(3)
51 #define	ISNS_RCV_TIMER_SECONDS	5
52 
53 #define	VALID_NAME(NAME, LEN)	\
54 ((LEN) > 0 && (NAME)[0] != 0 && (NAME)[(LEN) - 1] == 0)
55 
56 static kmutex_t		isns_mutex;
57 static kthread_t	*isns_monitor_thr_id;
58 static kt_did_t		isns_monitor_thr_did;
59 static boolean_t	isns_monitor_thr_running;
60 
61 static kcondvar_t	isns_idle_cv;
62 
63 static uint16_t		xid;
64 #define	GET_XID()	atomic_inc_16_nv(&xid)
65 
66 static clock_t		monitor_idle_interval;
67 
68 #define	ISNS_GLOBAL_LOCK() \
69 	mutex_enter(&iscsit_global.global_isns_cfg.isns_mutex)
70 
71 #define	ISNS_GLOBAL_LOCK_HELD() \
72 	MUTEX_HELD(&iscsit_global.global_isns_cfg.isns_mutex)
73 
74 #define	ISNS_GLOBAL_UNLOCK() \
75 	mutex_exit(&iscsit_global.global_isns_cfg.isns_mutex)
76 
77 /*
78  * iSNS ESI thread state
79  */
80 
81 static kmutex_t		isns_esi_mutex;
82 static kcondvar_t	isns_esi_cv;
83 static list_t		esi_list;
84 static uint32_t		isns_esi_max_interval = 0;
85 
86 /*
87  * List of portals.
88  */
89 
90 static list_t		portal_list;
91 static uint32_t		portal_list_count = 0;
92 
93 /* How many of our portals are not "default"? */
94 static uint32_t		nondefault_portals = 0;
95 
96 /*
97  * Our entity identifier (fully-qualified hostname)
98  */
99 static char		*isns_eid = NULL;
100 
101 /*
102  * Our list of targets
103  */
104 static avl_tree_t	isns_target_list;
105 
106 static void
107 isnst_start();
108 
109 static void
110 isnst_stop();
111 
112 static void
113 iscsit_set_isns(boolean_t state);
114 
115 static int
116 iscsit_add_isns(it_portal_t *cfg_svr);
117 
118 static void
119 iscsit_delete_isns(iscsit_isns_svr_t *svr);
120 
121 static iscsit_isns_svr_t *
122 iscsit_isns_svr_lookup(struct sockaddr_storage *sa);
123 
124 static void
125 isnst_monitor(void *arg);
126 
127 static int
128 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled);
129 
130 static int
131 isnst_update_target(iscsit_tgt_t *target, isns_reg_type_t reg);
132 
133 static  int
134 isnst_update_one_server(iscsit_isns_svr_t *svr, iscsit_tgt_t *target,
135     isns_reg_type_t reg);
136 
137 static int isnst_register(iscsit_isns_svr_t *svr, iscsit_tgt_t *target,
138     isns_reg_type_t regtype);
139 static int isnst_deregister(iscsit_isns_svr_t *svr, char *node);
140 
141 static size_t
142 isnst_make_dereg_pdu(isns_pdu_t **pdu, char *node);
143 
144 static int
145 isnst_verify_rsp(isns_pdu_t *pdu, isns_pdu_t *rsp);
146 
147 static uint16_t
148 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp);
149 
150 static size_t
151 isnst_make_reg_pdu(isns_pdu_t **pdu, iscsit_tgt_t *target,
152     boolean_t svr_registered, isns_reg_type_t regtype);
153 
154 static size_t
155 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags);
156 
157 static int
158 isnst_add_attr(isns_pdu_t *pdu,
159     size_t max_pdu_size,
160     uint32_t attr_id,
161     uint32_t attr_len,
162     void *attr_data,
163     uint32_t attr_numeric_data);
164 
165 static int
166 isnst_send_pdu(void *so, isns_pdu_t *pdu);
167 
168 static size_t
169 isnst_rcv_pdu(void *so, isns_pdu_t **pdu);
170 
171 static void *
172 isnst_open_so(struct sockaddr_storage *sa);
173 
174 static void
175 isnst_close_so(void *);
176 
177 static void
178 isnst_esi_thread(void *arg);
179 
180 static boolean_t
181 isnst_handle_esi_req(ksocket_t so, isns_pdu_t *pdu, size_t pl_size);
182 
183 static void isnst_esi_start(isns_portal_list_t *portal);
184 static void isnst_esi_stop();
185 static void isnst_esi_stop_thread(isns_esi_tinfo_t *tinfop);
186 static void isnst_esi_check();
187 static void isnst_esi_start_thread(isns_esi_tinfo_t *tinfop);
188 static isns_target_t *isnst_add_to_target_list(iscsit_tgt_t *target);
189 int isnst_tgt_avl_compare(const void *t1, const void *t2);
190 static void isnst_get_target_list(void);
191 static void isnst_set_server_status(iscsit_isns_svr_t *svr,
192     boolean_t registered);
193 static void isnst_monitor_stop(void);
194 static void isns_remove_portal(isns_portal_list_t *p);
195 static void isnst_add_default_portals();
196 static int isnst_add_default_portal_attrs(isns_pdu_t *pdu, size_t pdu_size);
197 static void isnst_remove_default_portals();
198 static boolean_t isnst_retry_registration(int rsp_status_code);
199 
200 it_cfg_status_t
201 isnst_config_merge(it_config_t *cfg)
202 {
203 	boolean_t		new_isns_state = B_FALSE;
204 	iscsit_isns_svr_t	*isns_svr, *next_isns_svr;
205 	it_portal_t		*cfg_isns_svr;
206 
207 	/*
208 	 * Determine whether iSNS is enabled in the new config.
209 	 * Isns property may not be set up yet.
210 	 */
211 	(void) nvlist_lookup_boolean_value(cfg->config_global_properties,
212 	    PROP_ISNS_ENABLED, &new_isns_state);
213 
214 	ISNS_GLOBAL_LOCK();
215 
216 	/* Delete iSNS servers that are no longer part of the config */
217 	for (isns_svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
218 	    isns_svr != NULL;
219 	    isns_svr = next_isns_svr) {
220 		next_isns_svr = list_next(
221 		    &iscsit_global.global_isns_cfg.isns_svrs, isns_svr);
222 		if (it_sns_svr_lookup(cfg, &isns_svr->svr_sa) == NULL)
223 			iscsit_delete_isns(isns_svr);
224 	}
225 
226 	/* Add new iSNS servers */
227 	for (cfg_isns_svr = cfg->config_isns_svr_list;
228 	    cfg_isns_svr != NULL;
229 	    cfg_isns_svr = cfg_isns_svr->next) {
230 		isns_svr = iscsit_isns_svr_lookup(&cfg_isns_svr->portal_addr);
231 		if (isns_svr == NULL) {
232 			if (iscsit_add_isns(cfg_isns_svr) != 0) {
233 				/* Shouldn't happen */
234 				ISNS_GLOBAL_UNLOCK();
235 				return (ITCFG_MISC_ERR);
236 			}
237 		}
238 	}
239 
240 	/* Start/Stop iSNS if necessary */
241 	if (iscsit_global.global_isns_cfg.isns_state != new_isns_state) {
242 		iscsit_set_isns(new_isns_state);
243 	}
244 
245 	ISNS_GLOBAL_UNLOCK();
246 
247 	/*
248 	 * There is no "modify case" since the user specifies a complete
249 	 * server list each time.  A modify is the same as a remove+add.
250 	 */
251 
252 	return (0);
253 }
254 
255 int
256 iscsit_isns_init(iscsit_hostinfo_t *hostinfo)
257 {
258 	mutex_init(&iscsit_global.global_isns_cfg.isns_mutex, NULL,
259 	    MUTEX_DEFAULT, NULL);
260 
261 	ISNS_GLOBAL_LOCK();
262 	iscsit_global.global_isns_cfg.isns_state = B_FALSE;
263 	list_create(&iscsit_global.global_isns_cfg.isns_svrs,
264 	    sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln));
265 	list_create(&portal_list, sizeof (isns_portal_list_t),
266 	    offsetof(isns_portal_list_t, portal_ln));
267 	list_create(&esi_list, sizeof (isns_esi_tinfo_t),
268 	    offsetof(isns_esi_tinfo_t, esi_ln));
269 	portal_list_count = 0;
270 	isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP);
271 	if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN)
272 		hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN;
273 	(void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length);
274 	avl_create(&isns_target_list, isnst_tgt_avl_compare,
275 	    sizeof (isns_target_t), offsetof(isns_target_t, target_node));
276 	/*
277 	 * The iscsi global lock is not held here, but it is held when
278 	 * isnst_start is called, so we need to acquire it only in this
279 	 * case.
280 	 */
281 	ISCSIT_GLOBAL_LOCK(RW_READER);
282 	isnst_get_target_list();
283 	ISCSIT_GLOBAL_UNLOCK();
284 
285 	/* initialize isns client */
286 	mutex_init(&isns_mutex, NULL, MUTEX_DEFAULT, NULL);
287 	mutex_init(&isns_esi_mutex, NULL, MUTEX_DEFAULT, NULL);
288 	isns_monitor_thr_id = NULL;
289 	monitor_idle_interval = ISNS_IDLE_TIME * drv_usectohz(1000000);
290 	cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL);
291 	cv_init(&isns_esi_cv, NULL, CV_DEFAULT, NULL);
292 	xid = 0;
293 	ISNS_GLOBAL_UNLOCK();
294 
295 	return (0);
296 }
297 
298 static void
299 isnst_esi_stop_thread(isns_esi_tinfo_t *tinfop)
300 {
301 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
302 	ASSERT(mutex_owned(&isns_esi_mutex));
303 
304 	list_remove(&esi_list, tinfop);
305 
306 	/*
307 	 * The only way to break a thread waiting in ksocket_accept() is to call
308 	 * ksocket_close.
309 	 */
310 	mutex_exit(&isns_esi_mutex);
311 	ISNS_GLOBAL_UNLOCK();
312 	idm_soshutdown(tinfop->esi_so);
313 	idm_sodestroy(tinfop->esi_so);
314 	thread_join(tinfop->esi_thread_did);
315 	ISNS_GLOBAL_LOCK();
316 	mutex_enter(&isns_esi_mutex);
317 
318 	tinfop->esi_thread_running = B_FALSE;
319 	tinfop->esi_so = NULL;
320 	tinfop->esi_port = 0;
321 	tinfop->esi_registered = B_FALSE;
322 	cv_signal(&isns_esi_cv);
323 	tinfop->esi_portal->portal_esi = NULL;
324 	kmem_free(tinfop, sizeof (isns_esi_tinfo_t));
325 }
326 
327 static void
328 isnst_esi_stop()
329 {
330 	/*
331 	 * Basically, we just wait for all the threads to stop.  They
332 	 * should already be in the process of shutting down.
333 	 */
334 
335 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
336 
337 	ISNS_GLOBAL_UNLOCK();
338 	mutex_enter(&isns_esi_mutex);
339 	while (!list_is_empty(&esi_list)) {
340 		cv_wait(&isns_esi_cv, &isns_esi_mutex);
341 	}
342 	mutex_exit(&isns_esi_mutex);
343 	ISNS_GLOBAL_LOCK();
344 }
345 
346 void
347 iscsit_isns_fini()
348 {
349 	ISNS_GLOBAL_LOCK();
350 	iscsit_set_isns(B_FALSE);
351 	mutex_destroy(&isns_mutex);
352 	cv_destroy(&isns_idle_cv);
353 	list_destroy(&esi_list);
354 	mutex_destroy(&isns_esi_mutex);
355 	cv_destroy(&isns_esi_cv);
356 
357 	/*
358 	 * Free our EID and target list.
359 	 */
360 
361 	if (isns_eid) {
362 		kmem_free(isns_eid, strlen(isns_eid) + 1);
363 		isns_eid = NULL;
364 	}
365 
366 	iscsit_global.global_isns_cfg.isns_state = B_FALSE;
367 	avl_destroy(&isns_target_list);
368 	list_destroy(&iscsit_global.global_isns_cfg.isns_svrs);
369 	list_destroy(&portal_list);
370 	portal_list_count = 0;
371 	ISNS_GLOBAL_UNLOCK();
372 
373 	mutex_destroy(&iscsit_global.global_isns_cfg.isns_mutex);
374 }
375 
376 static void
377 iscsit_set_isns(boolean_t state)
378 {
379 	iscsit_isns_svr_t	*svr;
380 
381 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
382 
383 	/* reset retry count for all servers */
384 	for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
385 	    svr != NULL;
386 	    svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
387 		svr->svr_retry_count = 0;
388 	}
389 
390 	/*
391 	 * Update state and isns stop flag
392 	 */
393 	iscsit_global.global_isns_cfg.isns_state = state;
394 
395 	if (state) {
396 		isnst_start();
397 	} else {
398 		isnst_stop();
399 	}
400 }
401 
402 int
403 iscsit_add_isns(it_portal_t *cfg_svr)
404 {
405 	iscsit_isns_svr_t *svr;
406 
407 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
408 
409 	svr = kmem_zalloc(sizeof (iscsit_isns_svr_t), KM_SLEEP);
410 	bcopy(&cfg_svr->portal_addr, &svr->svr_sa,
411 	    sizeof (struct sockaddr_storage));
412 
413 	/* put it on the global isns server list */
414 	list_insert_tail(&iscsit_global.global_isns_cfg.isns_svrs, svr);
415 
416 	/*
417 	 * Register targets with this server if iSNS is enabled.
418 	 */
419 
420 	if (iscsit_global.global_isns_cfg.isns_state &&
421 	    (isnst_update_one_server(svr, NULL, ISNS_REGISTER_ALL) == 0)) {
422 		isnst_set_server_status(svr, B_TRUE);
423 	}
424 
425 	return (0);
426 }
427 
428 void
429 iscsit_delete_isns(iscsit_isns_svr_t *svr)
430 {
431 	boolean_t	need_dereg;
432 
433 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
434 
435 	list_remove(&iscsit_global.global_isns_cfg.isns_svrs, svr);
436 
437 	/* talk to this server if isns monitor is running */
438 	mutex_enter(&isns_mutex);
439 	if (isns_monitor_thr_id != NULL) {
440 		need_dereg = B_TRUE;
441 	} else {
442 		need_dereg = B_FALSE;
443 	}
444 	mutex_exit(&isns_mutex);
445 
446 	if (need_dereg) {
447 		(void) isnst_monitor_one_server(svr, B_FALSE);
448 	}
449 
450 	/* free the memory */
451 	kmem_free(svr, sizeof (*svr));
452 }
453 
454 static iscsit_isns_svr_t *
455 iscsit_isns_svr_lookup(struct sockaddr_storage *sa)
456 {
457 	iscsit_isns_svr_t	*svr;
458 	it_portal_t		portal1;
459 
460 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
461 
462 	bcopy(sa, &portal1.portal_addr, sizeof (struct sockaddr_storage));
463 
464 	for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
465 	    svr != NULL;
466 	    svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
467 		if (it_sa_compare(&svr->svr_sa, sa) == 0)
468 			return (svr);
469 	}
470 
471 	return (NULL);
472 }
473 
474 int
475 iscsit_isns_register(iscsit_tgt_t *target)
476 {
477 	int rc = 0;
478 
479 	ISNS_GLOBAL_LOCK();
480 
481 	(void) isnst_add_to_target_list(target);
482 
483 	if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) {
484 		ISNS_GLOBAL_UNLOCK();
485 		return (rc);
486 	}
487 
488 	rc = isnst_update_target(target, ISNS_REGISTER_TARGET);
489 
490 	ISNS_GLOBAL_UNLOCK();
491 
492 	return (rc);
493 }
494 
495 int
496 iscsit_isns_deregister(iscsit_tgt_t *target)
497 {
498 	void				*itarget;
499 	isns_target_t			tmptgt;
500 	iscsit_isns_svr_t		*svr;
501 	list_t				*global;
502 
503 	ISNS_GLOBAL_LOCK();
504 
505 	if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) {
506 		tmptgt.target = target;
507 
508 		if ((itarget = avl_find(&isns_target_list, &tmptgt, NULL))
509 		    != NULL) {
510 			avl_remove(&isns_target_list, itarget);
511 			kmem_free(itarget, sizeof (isns_target_t));
512 		}
513 
514 		ISNS_GLOBAL_UNLOCK();
515 		return (0);
516 	}
517 
518 	/*
519 	 * Don't worry about dereg failures.
520 	 */
521 	(void) isnst_update_target(target, ISNS_DEREGISTER_TARGET);
522 
523 	/*
524 	 * Remove the target from the list regardless of the status.
525 	 */
526 
527 	tmptgt.target = target;
528 	if ((itarget = avl_find(&isns_target_list, &tmptgt, NULL)) != NULL) {
529 		avl_remove(&isns_target_list, itarget);
530 		kmem_free(itarget, sizeof (isns_target_t));
531 	}
532 
533 	/*
534 	 * If there are no more targets, mark the server as
535 	 * unregistered.
536 	 */
537 
538 	if (avl_numnodes(&isns_target_list) == 0) {
539 		global = &iscsit_global.global_isns_cfg.isns_svrs;
540 		for (svr = list_head(global); svr != NULL;
541 		    svr = list_next(global, svr)) {
542 			isnst_set_server_status(svr, B_FALSE);
543 		}
544 	}
545 
546 	ISNS_GLOBAL_UNLOCK();
547 
548 	return (0);
549 }
550 
551 /*
552  * This function is called by iscsit when a target's configuration
553  * has changed.
554  */
555 
556 void
557 iscsit_isns_target_update(iscsit_tgt_t *target)
558 {
559 	ISNS_GLOBAL_LOCK();
560 
561 	if (iscsit_global.global_isns_cfg.isns_state == B_FALSE) {
562 		ISNS_GLOBAL_UNLOCK();
563 		return;
564 	}
565 
566 	(void) isnst_update_target(target, ISNS_UPDATE_TARGET);
567 
568 	ISNS_GLOBAL_UNLOCK();
569 }
570 
571 static void
572 isnst_start()
573 {
574 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
575 
576 	/*
577 	 * Get target and portal lists, then start ESI threads for each portal.
578 	 */
579 
580 	isnst_get_target_list();
581 	isnst_add_default_portals();
582 
583 	/*
584 	 * Create a thread for monitoring server communications
585 	 */
586 	mutex_enter(&isns_mutex);
587 	isns_monitor_thr_id = thread_create(NULL, 0,
588 	    isnst_monitor, NULL, 0, &p0, TS_RUN, minclsyspri);
589 	while (!isns_monitor_thr_running)
590 		cv_wait(&isns_idle_cv, &isns_mutex);
591 	mutex_exit(&isns_mutex);
592 }
593 
594 static void
595 isnst_monitor_stop(void)
596 {
597 	mutex_enter(&isns_mutex);
598 	if (isns_monitor_thr_running) {
599 		isns_monitor_thr_running = B_FALSE;
600 		cv_signal(&isns_idle_cv);
601 		mutex_exit(&isns_mutex);
602 
603 		thread_join(isns_monitor_thr_did);
604 		return;
605 	}
606 	mutex_exit(&isns_mutex);
607 }
608 
609 static void
610 isnst_stop()
611 {
612 	isns_target_t *itarget;
613 
614 	isnst_remove_default_portals();
615 	isnst_esi_stop();
616 	ISNS_GLOBAL_UNLOCK();
617 	isnst_monitor_stop();
618 	ISNS_GLOBAL_LOCK();
619 	while ((itarget = avl_first(&isns_target_list)) != NULL) {
620 		avl_remove(&isns_target_list, itarget);
621 		kmem_free(itarget, sizeof (isns_target_t));
622 	}
623 }
624 
625 /*
626  * isnst_update_server_timestamp
627  *
628  * When we receive an ESI request, update the timestamp for the server.
629  * If we don't receive one for the specified period of time, we'll attempt
630  * to re-register.
631  */
632 
633 static void
634 isnst_update_server_timestamp(ksocket_t so)
635 {
636 	iscsit_isns_svr_t	*svr;
637 	struct in_addr		*sin = NULL, *svr_in;
638 	struct in6_addr		*sin6 = NULL, *svr_in6;
639 	struct sockaddr_in6	t_addr;
640 	socklen_t		t_addrlen;
641 
642 	bzero(&t_addr, sizeof (struct sockaddr_in6));
643 	t_addrlen = sizeof (struct sockaddr_in6);
644 	(void) ksocket_getpeername(so, (struct sockaddr *)&t_addr, &t_addrlen,
645 	    CRED());
646 	if (((struct sockaddr *)(&t_addr))->sa_family == AF_INET) {
647 		sin = &((struct sockaddr_in *)((void *)(&t_addr)))->sin_addr;
648 	} else {
649 		sin6 = &(&t_addr)->sin6_addr;
650 	}
651 
652 	/*
653 	 * Find the server and update the timestamp
654 	 */
655 
656 	ISNS_GLOBAL_LOCK();
657 	for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
658 	    svr != NULL;
659 	    svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
660 		if (sin6 == NULL) {
661 			if (svr->svr_sa.ss_family == AF_INET) {
662 				svr_in = &((struct sockaddr_in *)&svr->svr_sa)->
663 				    sin_addr;
664 				if (bcmp(svr_in, sin, sizeof (in_addr_t))
665 				    == 0) {
666 					break;
667 				}
668 			}
669 		} else {
670 			if (svr->svr_sa.ss_family == AF_INET6) {
671 				svr_in6 = &((struct sockaddr_in6 *)
672 				    &svr->svr_sa)->sin6_addr;
673 				if (bcmp(svr_in6, sin6,
674 				    sizeof (in6_addr_t)) == 0) {
675 					break;
676 				}
677 			}
678 		}
679 	}
680 
681 	if (svr != NULL) {
682 		svr->svr_last_msg = ddi_get_lbolt();
683 	}
684 	ISNS_GLOBAL_UNLOCK();
685 }
686 
687 /*
688  * isnst_monitor
689  *
690  * This function monitors registration status for each server.
691  */
692 
693 
694 static void
695 isnst_monitor_all_servers()
696 {
697 	iscsit_isns_svr_t	*svr;
698 	boolean_t		enabled;
699 	list_t			*svr_list;
700 
701 	svr_list = &iscsit_global.global_isns_cfg.isns_svrs;
702 
703 	ISNS_GLOBAL_LOCK();
704 	enabled = iscsit_global.global_isns_cfg.isns_state;
705 	for (svr = list_head(svr_list); svr != NULL;
706 	    svr = list_next(svr_list, svr)) {
707 		if (isnst_monitor_one_server(svr, enabled) != 0) {
708 			svr->svr_retry_count++;
709 		} else {
710 			svr->svr_retry_count = 0;
711 		}
712 	}
713 	ISNS_GLOBAL_UNLOCK();
714 }
715 
716 /*ARGSUSED*/
717 static void
718 isnst_monitor(void *arg)
719 {
720 	mutex_enter(&isns_mutex);
721 	cv_signal(&isns_idle_cv);
722 	isns_monitor_thr_did = curthread->t_did;
723 	isns_monitor_thr_running = B_TRUE;
724 
725 	while (isns_monitor_thr_running) {
726 		mutex_exit(&isns_mutex);
727 
728 		/* Update servers */
729 		isnst_monitor_all_servers();
730 
731 		/*
732 		 * Keep running until isns_monitor_thr_running is set to
733 		 * B_FALSE.
734 		 */
735 		mutex_enter(&isns_mutex);
736 		DTRACE_PROBE(iscsit__isns__monitor__sleep);
737 		(void) cv_timedwait(&isns_idle_cv, &isns_mutex,
738 		    ddi_get_lbolt() + monitor_idle_interval);
739 		DTRACE_PROBE1(iscsit__isns__monitor__wakeup,
740 		    boolean_t, isns_monitor_thr_running);
741 	}
742 
743 	mutex_exit(&isns_mutex);
744 
745 	/* Update the servers one last time for deregistration */
746 	isnst_monitor_all_servers();
747 
748 	/* terminate the thread at the last */
749 	thread_exit();
750 }
751 
752 static int
753 isnst_monitor_one_server(iscsit_isns_svr_t *svr, boolean_t enabled)
754 {
755 	int		rc = 0;
756 	struct sonode	*so;
757 
758 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
759 
760 	/*
761 	 * First, take care of the case where iSNS is no longer enabled.
762 	 *
763 	 * If we're still registered, deregister.  Regardless, mark the
764 	 * server as not registered.
765 	 */
766 
767 	if (enabled == B_FALSE) {
768 		if (svr->svr_registered == B_TRUE) {
769 			/*
770 			 * Doesn't matter if this fails.  We're disabled.
771 			 */
772 			so = isnst_open_so(&svr->svr_sa);
773 			if (so != NULL) {
774 				(void) isnst_update_one_server(svr, NULL,
775 				    ISNS_DEREGISTER_ALL);
776 				isnst_close_so(so);
777 			}
778 		}
779 
780 		isnst_set_server_status(svr, B_FALSE);
781 		return (0);
782 	}
783 
784 	/*
785 	 * If there are no targets, we're done.
786 	 */
787 
788 	if (avl_numnodes(&isns_target_list) == 0) {
789 		return (0);
790 	}
791 
792 	/*
793 	 * At this point, we know iSNS is enabled.
794 	 *
795 	 * If we've received an ESI request from the server recently
796 	 * (within MAX_ESI_INTERVALS * the max interval length),
797 	 * no need to continue.
798 	 */
799 
800 	if (svr->svr_registered == B_TRUE) {
801 		if (ddi_get_lbolt() < (svr->svr_last_msg +
802 		    drv_usectohz(isns_esi_max_interval * 1000000 *
803 		    MAX_ESI_INTERVALS))) {
804 			return (0);
805 		}
806 	} else {
807 		/*
808 		 * We're not registered... Try to register now.
809 		 */
810 		if ((rc = isnst_update_one_server(svr, NULL,
811 		    ISNS_REGISTER_ALL)) == 0) {
812 			isnst_set_server_status(svr, B_TRUE);
813 		}
814 	}
815 
816 	return (rc);
817 }
818 
819 static int
820 isnst_update_target(iscsit_tgt_t *target, isns_reg_type_t reg)
821 {
822 	iscsit_isns_svr_t	*svr;
823 	int			rc = 0, curr_rc;
824 
825 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
826 	ASSERT(iscsit_global.global_isns_cfg.isns_state == B_TRUE);
827 
828 	for (svr = list_head(&iscsit_global.global_isns_cfg.isns_svrs);
829 	    svr != NULL;
830 	    svr = list_next(&iscsit_global.global_isns_cfg.isns_svrs, svr)) {
831 		/*
832 		 * Only return success if they all succeed.  Let the caller
833 		 * deal with any failure.
834 		 */
835 
836 		curr_rc = isnst_update_one_server(svr, target, reg);
837 
838 		if (curr_rc == 0) {
839 			if (reg == ISNS_REGISTER_TARGET) {
840 				isnst_set_server_status(svr, B_TRUE);
841 			}
842 		} else if (rc == 0) {
843 			rc = curr_rc;
844 		}
845 	}
846 
847 	return (rc);
848 }
849 
850 static int
851 isnst_update_one_server(iscsit_isns_svr_t *svr, iscsit_tgt_t *target,
852     isns_reg_type_t reg)
853 {
854 	int rc = 0;
855 
856 	switch (reg) {
857 	case ISNS_DEREGISTER_TARGET:
858 		rc = isnst_deregister(svr, target->target_name);
859 		break;
860 
861 	case ISNS_DEREGISTER_ALL:
862 		rc = isnst_deregister(svr, NULL);
863 		break;
864 
865 	case ISNS_UPDATE_TARGET:
866 	case ISNS_REGISTER_TARGET:
867 		rc = isnst_register(svr, target, reg);
868 		break;
869 
870 	case ISNS_REGISTER_ALL:
871 		rc = isnst_register(svr, NULL, reg);
872 		break;
873 
874 	default:
875 		ASSERT(0);
876 		/* NOTREACHED */
877 	}
878 
879 	return (rc);
880 }
881 
882 /*
883  * isnst_retry_registration
884  *
885  * This function checks the return value from a registration pdu and
886  * determines whether or not we should retry this request.  If the
887  * request is retried, it will do so as an "update", which means we
888  * re-register everything.
889  */
890 
891 static boolean_t
892 isnst_retry_registration(int rsp_status_code)
893 {
894 	boolean_t retry;
895 
896 	/*
897 	 * Currently, we will attempt to retry for "Invalid Registration",
898 	 * "Source Unauthorized", or "Busy" errors.  Any other errors should
899 	 * be handled by the caller if necessary.
900 	 */
901 
902 	switch (rsp_status_code) {
903 	case ISNS_RSP_INVALID_REGIS:
904 	case ISNS_RSP_SRC_UNAUTHORIZED:
905 	case ISNS_RSP_BUSY:
906 		retry = B_TRUE;
907 		break;
908 	default:
909 		retry = B_FALSE;
910 		break;
911 	}
912 
913 	return (retry);
914 }
915 
916 static int
917 isnst_register(iscsit_isns_svr_t *svr, iscsit_tgt_t *target,
918     isns_reg_type_t regtype)
919 {
920 	struct sonode	*so;
921 	int		rc = 0;
922 	isns_pdu_t	*pdu, *rsp;
923 	size_t		pdu_size, rsp_size;
924 	isns_target_t	*itarget, tmptgt;
925 	boolean_t	retry_reg = B_TRUE;
926 
927 	/*
928 	 * Registration is a tricky thing.  In order to keep things simple,
929 	 * we don't want to keep track of which targets are registered to
930 	 * which server.  We rely on the target state machine to tell us
931 	 * when a target is online or offline, which prompts us to either
932 	 * register or deregister that target.
933 	 *
934 	 * When iscsit_isns_init is called, get a list of targets.  Those that
935 	 * are online will need to be registered.  In this case, target
936 	 * will be NULL.
937 	 *
938 	 * What this means is that if svr_registered == B_FALSE, that's
939 	 * when we'll register the network entity as well.
940 	 */
941 
942 	if ((avl_numnodes(&isns_target_list) == 0) && (target == NULL)) {
943 		return (0);
944 	}
945 
946 	/*
947 	 * If the target is already registered and we're not doing an
948 	 * update registration, just return.
949 	 */
950 
951 	if (target != NULL) {
952 		tmptgt.target = target;
953 		itarget = avl_find(&isns_target_list, &tmptgt, NULL);
954 		ASSERT(itarget);
955 		if ((itarget->target_registered == B_TRUE) &&
956 		    (regtype != ISNS_UPDATE_TARGET)) {
957 			return (0);
958 		}
959 	}
960 
961 	isnst_esi_check();
962 
963 	/* create TCP connection to the isns server */
964 	so = isnst_open_so(&svr->svr_sa);
965 
966 	if (so == NULL) {
967 		isnst_set_server_status(svr, B_FALSE);
968 		return (-1);
969 	}
970 
971 	while (retry_reg) {
972 		pdu_size = isnst_make_reg_pdu(&pdu, target, svr->svr_registered,
973 		    regtype);
974 		if (pdu_size == 0) {
975 			isnst_close_so(so);
976 			return (-1);
977 		}
978 
979 		rc = isnst_send_pdu(so, pdu);
980 		if (rc != 0) {
981 			kmem_free(pdu, pdu_size);
982 			isnst_close_so(so);
983 			return (rc);
984 		}
985 
986 		rsp_size = isnst_rcv_pdu(so, &rsp);
987 		if (rsp_size == 0) {
988 			kmem_free(pdu, pdu_size);
989 			isnst_close_so(so);
990 			return (-1);
991 		}
992 
993 		rc = isnst_verify_rsp(pdu, rsp);
994 
995 		/*
996 		 * If we got a registration error, the server may be out of
997 		 * sync.  In this case, we may re-try the registration as
998 		 * a "target update", which causes us to re-register everything.
999 		 */
1000 
1001 		if ((retry_reg = isnst_retry_registration(rc)) == B_TRUE) {
1002 			if (regtype == ISNS_UPDATE_TARGET) {
1003 				/*
1004 				 * If registration failed on an update, there
1005 				 * is something terribly wrong, possibly with
1006 				 * the server.
1007 				 */
1008 				rc = -1;
1009 				retry_reg = B_FALSE;
1010 				isnst_set_server_status(svr, B_FALSE);
1011 			} else {
1012 				regtype = ISNS_UPDATE_TARGET;
1013 			}
1014 		}
1015 
1016 		kmem_free(pdu, pdu_size);
1017 		kmem_free(rsp, rsp_size);
1018 	}
1019 
1020 	isnst_close_so(so);
1021 
1022 	/*
1023 	 * If it succeeded, mark all registered targets as such
1024 	 */
1025 	if (rc == 0) {
1026 		if ((target != NULL) && (regtype != ISNS_UPDATE_TARGET)) {
1027 			/* itarget initialized above */
1028 			itarget->target_registered = B_TRUE;
1029 		} else {
1030 			itarget = avl_first(&isns_target_list);
1031 			while (itarget) {
1032 				itarget->target_registered = B_TRUE;
1033 				itarget = AVL_NEXT(&isns_target_list, itarget);
1034 			}
1035 		}
1036 	}
1037 
1038 	return (rc);
1039 }
1040 
1041 static isns_portal_list_t *
1042 isns_lookup_portal(struct sockaddr_storage *p)
1043 {
1044 	isns_portal_list_t *portal;
1045 
1046 	portal = list_head(&portal_list);
1047 
1048 	while (portal != NULL) {
1049 		if (bcmp(p, &portal->portal_addr,
1050 		    sizeof (struct sockaddr_storage)) == 0) {
1051 			return (portal);
1052 		}
1053 		portal = list_next(&portal_list, portal);
1054 	}
1055 
1056 	return (NULL);
1057 }
1058 
1059 static void
1060 isns_remove_portal(isns_portal_list_t *p)
1061 {
1062 	list_remove(&portal_list, p);
1063 	kmem_free(p, sizeof (isns_portal_list_t));
1064 	portal_list_count--;
1065 }
1066 
1067 static isns_target_t *
1068 isnst_add_to_target_list(iscsit_tgt_t *target)
1069 {
1070 	isns_target_t *itarget, tmptgt;
1071 
1072 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
1073 
1074 	/*
1075 	 * Make sure this target isn't already in our list.  If it is,
1076 	 * perhaps it has just moved from offline to online.
1077 	 */
1078 
1079 	tmptgt.target = target;
1080 	if ((itarget = (isns_target_t *)avl_find(&isns_target_list,
1081 	    &tmptgt, NULL)) == NULL) {
1082 		itarget = kmem_zalloc(sizeof (isns_target_t), KM_NOSLEEP);
1083 
1084 		/*
1085 		 * If we can't get memory, we're not going to be able to
1086 		 * register this target.  This needs to be fixed up.
1087 		 */
1088 		if (itarget == NULL)
1089 			return (NULL);
1090 
1091 		itarget->target = target;
1092 		avl_add(&isns_target_list, itarget);
1093 	}
1094 
1095 	return (itarget);
1096 }
1097 
1098 static int
1099 isnst_add_default_portal_attrs(isns_pdu_t *pdu, size_t pdu_size)
1100 {
1101 	isns_portal_list_t	*portal;
1102 	struct sockaddr_in	*in;
1103 	struct sockaddr_in6	*in6;
1104 	int			idx = 0;
1105 	uint32_t		attr_data;
1106 	void			*inaddrp;
1107 
1108 	portal = list_head(&portal_list);
1109 
1110 	while (portal) {
1111 		if (idx == nondefault_portals) {
1112 			break;
1113 		}
1114 
1115 		if (portal->portal_iscsit == NULL) {
1116 			in = (struct sockaddr_in *)&portal->portal_addr;
1117 
1118 			if (in->sin_family == AF_INET) {
1119 				attr_data = sizeof (in_addr_t);
1120 				inaddrp = (void *)&in->sin_addr;
1121 			} else if (in->sin_family == AF_INET6) {
1122 				in6 = (struct sockaddr_in6 *)
1123 				    &portal->portal_addr;
1124 				attr_data = sizeof (in6_addr_t);
1125 				inaddrp = (void *)&in6->sin6_addr;
1126 			} else {
1127 				return (-1);
1128 			}
1129 
1130 			if (isnst_add_attr(pdu, pdu_size,
1131 			    ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 16, inaddrp,
1132 			    attr_data) != 0) {
1133 				return (-1);
1134 			}
1135 
1136 			/* Portal Group Portal Port */
1137 			if (isnst_add_attr(pdu, pdu_size,
1138 			    ISNS_PG_PORTAL_PORT_ATTR_ID, 4, 0,
1139 			    ntohs(in->sin_port)) != 0) {
1140 				return (-1);
1141 			}
1142 
1143 			idx++;
1144 		}
1145 
1146 		portal = list_next(&portal_list, portal);
1147 	}
1148 
1149 	return (0);
1150 }
1151 
1152 static size_t
1153 isnst_make_reg_pdu(isns_pdu_t **pdu, iscsit_tgt_t *target,
1154     boolean_t svr_registered, isns_reg_type_t regtype)
1155 {
1156 	size_t			pdu_size;
1157 	iscsit_tpgt_t		*tpgt;
1158 	iscsit_tpg_t		*tpg;
1159 	iscsit_portal_t		*tp;
1160 	char			*str;
1161 	int			len;
1162 	isns_portal_list_t	*portal;
1163 	isns_esi_tinfo_t	*tinfop;
1164 	isns_target_t		*itarget;
1165 	iscsit_tgt_t		*src;
1166 	boolean_t		reg_all = B_FALSE;
1167 	uint16_t		flags = 0;
1168 
1169 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
1170 
1171 	/*
1172 	 * Find a source attribute for this registration.
1173 	 *
1174 	 * If we're already registered, registering for the first time, or
1175 	 * updating a target, we'll use the target_name of the first target
1176 	 * in our list.
1177 	 *
1178 	 * The alternate case is that we're registering for the first time,
1179 	 * but target is non-NULL.  In that case, we have no targets in our
1180 	 * list yet, so we use the passed in target's name.
1181 	 */
1182 
1183 	if (svr_registered || (target == NULL) ||
1184 	    (regtype == ISNS_UPDATE_TARGET)) {
1185 		ASSERT(avl_numnodes(&isns_target_list) != 0);
1186 		itarget = (isns_target_t *)avl_first(&isns_target_list);
1187 		src = itarget->target;
1188 	} else {
1189 		src = target;
1190 	}
1191 
1192 	/*
1193 	 * No target means we're registering everything.  A regtype of
1194 	 * ISNS_UPDATE_TARGET means we're re-registering everything.
1195 	 * Whether we're registering or re-registering depends on if
1196 	 * we're already registered.
1197 	 */
1198 
1199 	if ((target == NULL) || (regtype == ISNS_UPDATE_TARGET)) {
1200 		reg_all = B_TRUE;
1201 		target = src;	/* This will be the 1st tgt in our list */
1202 
1203 		/*
1204 		 * If we're already registered, this will be a replacement
1205 		 * registration.  In this case, we need to make sure our
1206 		 * source attribute is an already registered target.
1207 		 */
1208 		if (svr_registered) {
1209 			flags = ISNS_FLAG_REPLACE_REG;
1210 			while (itarget->target_registered == B_FALSE) {
1211 				itarget = AVL_NEXT(&isns_target_list,
1212 				    itarget);
1213 			}
1214 			src = itarget->target;
1215 			/* Reset itarget to the beginning of our list */
1216 			itarget = (isns_target_t *)avl_first(&isns_target_list);
1217 		}
1218 	}
1219 
1220 	pdu_size = isnst_create_pdu_header(ISNS_DEV_ATTR_REG, pdu, flags);
1221 	if (pdu_size == 0) {
1222 		return (0);
1223 	}
1224 
1225 	len = strlen(src->target_name) + 1;
1226 	if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1227 	    len, src->target_name, 0) != 0) {
1228 		goto pdu_error;
1229 	}
1230 
1231 	/*
1232 	 * Message Key Attributes - EID
1233 	 */
1234 	len = strlen(isns_eid) + 1;
1235 
1236 	if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
1237 	    len, isns_eid, 0) != 0) {
1238 		goto pdu_error;
1239 	}
1240 
1241 	/* Delimiter */
1242 	if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID,
1243 	    0, 0, 0) != 0) {
1244 		goto pdu_error;
1245 	}
1246 
1247 	/*
1248 	 * Operating Attributes
1249 	 */
1250 	if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID, len,
1251 	    isns_eid, 0) != 0) {
1252 		goto pdu_error;
1253 	}
1254 
1255 	/* ENTITY Protocol - Section 6.2.2 */
1256 	if (isnst_add_attr(*pdu, pdu_size, ISNS_ENTITY_PROTOCOL_ATTR_ID,
1257 	    4, 0, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
1258 		goto pdu_error;
1259 	}
1260 
1261 	/*
1262 	 * Network entity portal information - only on the first registration.
1263 	 */
1264 
1265 	if (svr_registered == B_FALSE) {
1266 		struct sockaddr_in *sin;
1267 		int addrsize;
1268 
1269 		portal = list_head(&portal_list);
1270 
1271 		while (portal != NULL) {
1272 			sin = (struct sockaddr_in *)&portal->portal_addr;
1273 			tinfop = portal->portal_esi;
1274 
1275 			if (portal->portal_iscsit == NULL) {
1276 				if (sin->sin_family == AF_INET) {
1277 					addrsize = sizeof (struct in_addr);
1278 				} else {
1279 					addrsize = sizeof (struct in6_addr);
1280 				}
1281 
1282 				/* Portal IP Address */
1283 				if (isnst_add_attr(*pdu, pdu_size,
1284 				    ISNS_PORTAL_IP_ADDR_ATTR_ID, 16,
1285 				    &sin->sin_addr, addrsize) != 0) {
1286 					goto pdu_error;
1287 				}
1288 
1289 				/* Portal Port */
1290 				if (isnst_add_attr(*pdu, pdu_size,
1291 				    ISNS_PORTAL_PORT_ATTR_ID, 4, 0,
1292 				    ntohs(sin->sin_port)) != 0) {
1293 					goto pdu_error;
1294 				}
1295 
1296 				if (tinfop && tinfop->esi_port) {
1297 					/* ESI interval and port */
1298 					if (isnst_add_attr(*pdu, pdu_size,
1299 					    ISNS_ESI_INTERVAL_ATTR_ID, 4,
1300 					    NULL, 20) != 0) {
1301 						goto pdu_error;
1302 					}
1303 
1304 					if (isnst_add_attr(*pdu, pdu_size,
1305 					    ISNS_ESI_PORT_ATTR_ID, 4, NULL,
1306 					    tinfop->esi_port) != 0) {
1307 						goto pdu_error;
1308 					}
1309 				}
1310 			}
1311 
1312 			portal = list_next(&portal_list, portal);
1313 		}
1314 	}
1315 
1316 	do {
1317 		/* Hold the target mutex */
1318 		mutex_enter(&target->target_mutex);
1319 
1320 		/* iSCSI Name - Section 6.4.1 */
1321 		str = target->target_name;
1322 		len = strlen(str) + 1;
1323 		if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1324 		    len, str, 0) != 0) {
1325 			mutex_exit(&target->target_mutex);
1326 			goto pdu_error;
1327 		}
1328 
1329 		/* iSCSI Node Type */
1330 		if (isnst_add_attr(*pdu, pdu_size,
1331 		    ISNS_ISCSI_NODE_TYPE_ATTR_ID, 4, 0,
1332 		    ISNS_TARGET_NODE_TYPE) != 0) {
1333 			mutex_exit(&target->target_mutex);
1334 			goto pdu_error;
1335 		}
1336 
1337 		/* iSCSI Alias */
1338 #if 0
1339 		str = target->target_alias;
1340 #else
1341 		str = "Solaris iSCSI Target";
1342 #endif
1343 		if (str != NULL) {
1344 			len = strlen(str) + 1;
1345 			if (isnst_add_attr(*pdu, pdu_size,
1346 			    ISNS_ISCSI_ALIAS_ATTR_ID, len, str, 0) != 0) {
1347 				mutex_exit(&target->target_mutex);
1348 				goto pdu_error;
1349 			}
1350 		}
1351 
1352 		/* for each target portal group (start)... */
1353 		tpgt = avl_first(&target->target_tpgt_list);
1354 		ASSERT(tpgt != NULL);
1355 		do {
1356 			/* no need to explicitly register default PG */
1357 			if ((tpgt->tpgt_tag == ISCSIT_DEFAULT_TPGT) &&
1358 			    (avl_numnodes(&target->target_tpgt_list) == 1)) {
1359 				tpgt = AVL_NEXT(&target->target_tpgt_list,
1360 				    tpgt);
1361 				continue;
1362 			}
1363 
1364 			tpg = tpgt->tpgt_tpg;
1365 			mutex_enter(&tpg->tpg_mutex);
1366 
1367 			tp = avl_first(&tpg->tpg_portal_list);
1368 
1369 			/* Portal Group Tag */
1370 			if (isnst_add_attr(*pdu, pdu_size,
1371 			    ISNS_PG_TAG_ATTR_ID, 4, 0, tpgt->tpgt_tag) != 0) {
1372 				mutex_exit(&tpg->tpg_mutex);
1373 				mutex_exit(&target->target_mutex);
1374 				goto pdu_error;
1375 			}
1376 
1377 			ASSERT(tp != NULL);
1378 			do {
1379 				struct sockaddr_storage	*ss;
1380 				struct sockaddr_in	*in;
1381 				struct sockaddr_in6	*in6;
1382 				uint32_t attr_numeric_data;
1383 				void *inaddrp;
1384 
1385 				ss = &tp->portal_addr;
1386 				in = (struct sockaddr_in *)ss;
1387 				in6 = (struct sockaddr_in6 *)ss;
1388 
1389 				if (ss->ss_family == AF_INET) {
1390 					attr_numeric_data = sizeof (in_addr_t);
1391 					inaddrp = (void *)&in->sin_addr;
1392 				} else if (ss->ss_family == AF_INET6) {
1393 					attr_numeric_data = sizeof (in6_addr_t);
1394 					inaddrp = (void *)&in6->sin6_addr;
1395 				} else if (ss->ss_family == 0) {
1396 					/*
1397 					 * Need to add all default portals
1398 					 */
1399 					attr_numeric_data = 0;
1400 				} else {
1401 					cmn_err(CE_WARN, "Unknown address "
1402 					    "family for portal %p", (void *)tp);
1403 					mutex_exit(&tpg->tpg_mutex);
1404 					mutex_exit(&target->target_mutex);
1405 					goto pdu_error;
1406 				}
1407 
1408 				if (attr_numeric_data == 0) {
1409 					if (isnst_add_default_portal_attrs(*pdu,
1410 					    pdu_size) != 0) {
1411 						mutex_exit(&tpg->tpg_mutex);
1412 						mutex_exit(&target->
1413 						    target_mutex);
1414 						goto pdu_error;
1415 					}
1416 				} else {
1417 					/* Portal Group Portal IP Address */
1418 					if (isnst_add_attr(*pdu, pdu_size,
1419 					    ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 16,
1420 					    inaddrp, attr_numeric_data) != 0) {
1421 						mutex_exit(&tpg->tpg_mutex);
1422 						mutex_exit(&target->
1423 						    target_mutex);
1424 						goto pdu_error;
1425 					}
1426 
1427 					/* Portal Group Portal Port */
1428 					if (isnst_add_attr(*pdu, pdu_size,
1429 					    ISNS_PG_PORTAL_PORT_ATTR_ID,
1430 					    4, 0, ntohs(in->sin_port)) != 0) {
1431 						mutex_exit(&tpg->tpg_mutex);
1432 						mutex_exit(&target->
1433 						    target_mutex);
1434 						goto pdu_error;
1435 					}
1436 				}
1437 
1438 				tp = AVL_NEXT(&tpg->tpg_portal_list, tp);
1439 			} while (tp != NULL);
1440 
1441 			mutex_exit(&tpg->tpg_mutex);
1442 			tpgt = AVL_NEXT(&target->target_tpgt_list, tpgt);
1443 		} while (tpgt != NULL);
1444 		/* for each target portal group (end)... */
1445 
1446 		mutex_exit(&target->target_mutex);
1447 
1448 		if (reg_all) {
1449 			itarget = AVL_NEXT(&isns_target_list, itarget);
1450 			if (itarget) {
1451 				target = itarget->target;
1452 			} else {
1453 				target = NULL;
1454 			}
1455 		}
1456 	} while ((reg_all == B_TRUE) && (target != NULL));
1457 
1458 	return (pdu_size);
1459 
1460 pdu_error:
1461 	/* packet too large, no memory */
1462 	kmem_free(*pdu, pdu_size);
1463 	*pdu = NULL;
1464 
1465 	return (0);
1466 }
1467 
1468 static int
1469 isnst_deregister(iscsit_isns_svr_t *svr, char *node)
1470 {
1471 	int		rc;
1472 	isns_pdu_t	*pdu, *rsp;
1473 	size_t		pdu_size, rsp_size;
1474 	struct sonode	*so;
1475 
1476 	if ((svr->svr_registered == B_FALSE) ||
1477 	    (avl_numnodes(&isns_target_list) == 0)) {
1478 		return (0);
1479 	}
1480 
1481 	so = isnst_open_so(&svr->svr_sa);
1482 
1483 	if (so == NULL) {
1484 		return (-1);
1485 	}
1486 
1487 	pdu_size = isnst_make_dereg_pdu(&pdu, node);
1488 	if (pdu_size == 0) {
1489 		isnst_close_so(so);
1490 		return (-1);
1491 	}
1492 
1493 	rc = isnst_send_pdu(so, pdu);
1494 	if (rc != 0) {
1495 		isnst_close_so(so);
1496 		kmem_free(pdu, pdu_size);
1497 		return (rc);
1498 	}
1499 
1500 	rsp_size = isnst_rcv_pdu(so, &rsp);
1501 	if (rsp_size == 0) {
1502 		isnst_close_so(so);
1503 		kmem_free(pdu, pdu_size);
1504 		return (-1);
1505 	}
1506 
1507 	rc = isnst_verify_rsp(pdu, rsp);
1508 
1509 	isnst_close_so(so);
1510 	kmem_free(pdu, pdu_size);
1511 	kmem_free(rsp, rsp_size);
1512 
1513 	return (rc);
1514 }
1515 
1516 static size_t
1517 isnst_make_dereg_pdu(isns_pdu_t **pdu, char *node)
1518 {
1519 	size_t		pdu_size;
1520 	int		len;
1521 	isns_target_t	*itarget;
1522 	iscsit_tgt_t	*target;
1523 	int		num_targets;
1524 
1525 	/*
1526 	 * create DevDereg Message with all of target nodes
1527 	 */
1528 	pdu_size = isnst_create_pdu_header(ISNS_DEV_DEREG, pdu, 0);
1529 	if (pdu_size == 0) {
1530 		return (0);
1531 	}
1532 
1533 	/*
1534 	 * Source attribute - Must be a storage node in the same
1535 	 * network entity.  We'll just grab the first one in the list.
1536 	 * If it's the only online target, we turn this into a total
1537 	 * deregistration regardless of the value of "node".
1538 	 */
1539 
1540 	num_targets = avl_numnodes(&isns_target_list);
1541 	itarget = avl_first(&isns_target_list);
1542 	target = itarget->target;
1543 
1544 	len = strlen(target->target_name) + 1;
1545 	if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1546 	    len, target->target_name, 0) != 0) {
1547 		goto dereg_pdu_error;
1548 	}
1549 
1550 	/* Delimiter */
1551 	if (isnst_add_attr(*pdu, pdu_size, ISNS_DELIMITER_ATTR_ID,
1552 	    0, 0, 0) != 0) {
1553 		goto dereg_pdu_error;
1554 	}
1555 
1556 	/*
1557 	 * Operating attributes
1558 	 */
1559 	if ((node == NULL) || (num_targets == 1)) {
1560 		/* dereg everything */
1561 		len = strlen(isns_eid) + 1;
1562 		if (isnst_add_attr(*pdu, pdu_size, ISNS_EID_ATTR_ID,
1563 		    len, isns_eid, 0) != 0) {
1564 			goto dereg_pdu_error;
1565 		}
1566 	} else {
1567 		/* dereg one target only */
1568 		len = strlen(node) + 1;
1569 		if (isnst_add_attr(*pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID,
1570 		    len, node, 0) != 0) {
1571 			goto dereg_pdu_error;
1572 		}
1573 	}
1574 
1575 	return (pdu_size);
1576 
1577 dereg_pdu_error:
1578 	kmem_free(*pdu, pdu_size);
1579 	*pdu = NULL;
1580 
1581 	return (0);
1582 }
1583 
1584 static int
1585 isnst_verify_rsp(isns_pdu_t *pdu, isns_pdu_t *rsp)
1586 {
1587 	uint16_t	func_id;
1588 	uint16_t	payload_len, rsp_payload_len;
1589 	isns_resp_t	*resp;
1590 	uint8_t		*pp;
1591 	isns_tlv_t	*attr;
1592 	uint32_t	attr_len, attr_id, esi_interval;
1593 
1594 	/* validate response function id */
1595 	func_id = ntohs(rsp->func_id);
1596 	switch (ntohs(pdu->func_id)) {
1597 	case ISNS_DEV_ATTR_REG:
1598 		if (func_id != ISNS_DEV_ATTR_REG_RSP) {
1599 			return (-1);
1600 		}
1601 
1602 		/*
1603 		 * Get the ESI interval returned by the server.  It could
1604 		 * be different than what we asked for.  We never know which
1605 		 * portal a request may come in on, and any server could demand
1606 		 * any interval. We'll simply keep track of the largest interval
1607 		 * for use in monitoring.
1608 		 */
1609 
1610 		rsp_payload_len = isnst_pdu_get_op(rsp, &pp);
1611 		attr = (isns_tlv_t *)((void *)pp);
1612 
1613 		while (rsp_payload_len) {
1614 			attr_len = ntohl(attr->attr_len);
1615 			attr_id = ntohl(attr->attr_id);
1616 
1617 			if (attr_id == ISNS_ESI_INTERVAL_ATTR_ID) {
1618 				esi_interval =
1619 				    ntohl(*((uint32_t *)
1620 				    ((void *)(&attr->attr_value))));
1621 
1622 				if (esi_interval > isns_esi_max_interval)
1623 					isns_esi_max_interval = esi_interval;
1624 
1625 				break;
1626 			}
1627 
1628 			rsp_payload_len -= (8 + attr_len);
1629 			attr = (isns_tlv_t *)
1630 			    ((void *)((uint8_t *)attr + attr_len + 8));
1631 		}
1632 
1633 		break;
1634 	case ISNS_DEV_DEREG:
1635 		if (func_id != ISNS_DEV_DEREG_RSP) {
1636 			return (-1);
1637 		}
1638 		break;
1639 	default:
1640 		ASSERT(0);
1641 		break;
1642 	}
1643 
1644 	/* verify response transaction id */
1645 	if (ntohs(rsp->xid) != ntohs(pdu->xid)) {
1646 		return (-1);
1647 	}
1648 
1649 	/* check the error code */
1650 	payload_len = ntohs(rsp->payload_len);
1651 	resp = (isns_resp_t *)((void *)&rsp->payload[0]);
1652 	if (payload_len < 4) {
1653 		return (-1);
1654 	}
1655 
1656 	return (ntohl(resp->status));
1657 }
1658 
1659 static uint16_t
1660 isnst_pdu_get_op(isns_pdu_t *pdu, uint8_t **pp)
1661 {
1662 	uint8_t		*payload;
1663 	uint16_t	payload_len;
1664 	isns_resp_t	*resp;
1665 	isns_tlv_t	*attr;
1666 	uint32_t	attr_id;
1667 	uint32_t	tlv_len;
1668 
1669 	/* get payload */
1670 	payload_len = ntohs(pdu->payload_len);
1671 	resp = (isns_resp_t *)((void *)&pdu->payload[0]);
1672 
1673 	/* find the operating attributes */
1674 	ASSERT(payload_len >= 4);
1675 	payload_len -= 4;
1676 	payload = &resp->data[0];
1677 
1678 	while (payload_len >= 8) {
1679 		attr = (isns_tlv_t *)((void *)payload);
1680 		tlv_len = 8 + ntohl(attr->attr_len);
1681 		if (payload_len >= tlv_len) {
1682 			payload += tlv_len;
1683 			payload_len -= tlv_len;
1684 			attr_id = ntohl(attr->attr_id);
1685 			if (attr_id == ISNS_DELIMITER_ATTR_ID) {
1686 				break;
1687 			}
1688 		} else {
1689 			/* mal-formed packet */
1690 			payload = NULL;
1691 			payload_len = 0;
1692 		}
1693 	}
1694 
1695 	*pp = payload;
1696 
1697 	return (payload_len);
1698 }
1699 
1700 static size_t
1701 isnst_create_pdu_header(uint16_t func_id, isns_pdu_t **pdu, uint16_t flags)
1702 {
1703 	size_t	pdu_size = ISNSP_MAX_PDU_SIZE;
1704 
1705 	*pdu = (isns_pdu_t *)kmem_zalloc(pdu_size, KM_NOSLEEP);
1706 	if (*pdu != NULL) {
1707 		(*pdu)->version = htons((uint16_t)ISNSP_VERSION);
1708 		(*pdu)->func_id = htons((uint16_t)func_id);
1709 		(*pdu)->payload_len = htons(0);
1710 		(*pdu)->flags = htons(flags);
1711 
1712 		(*pdu)->xid = htons(GET_XID());
1713 		(*pdu)->seq = htons(0);
1714 	} else {
1715 		pdu_size = 0;
1716 	}
1717 
1718 	return (pdu_size);
1719 }
1720 
1721 static int
1722 isnst_add_attr(isns_pdu_t *pdu,
1723     size_t max_pdu_size,
1724     uint32_t attr_id,
1725     uint32_t attr_len,
1726     void *attr_data,
1727     uint32_t attr_numeric_data)
1728 {
1729 	isns_tlv_t	*attr_tlv;
1730 	uint8_t		*payload_ptr;
1731 	uint16_t	payload_len;
1732 	uint32_t	normalized_attr_len;
1733 	uint64_t	attr_tlv_len;
1734 
1735 	/* The attribute length must be 4-byte aligned. Section 5.1.3. */
1736 	normalized_attr_len = (attr_len % 4) == 0 ?
1737 	    (attr_len) : (attr_len + (4 - (attr_len % 4)));
1738 	attr_tlv_len = ISNS_TLV_ATTR_ID_LEN +
1739 	    ISNS_TLV_ATTR_LEN_LEN + normalized_attr_len;
1740 
1741 	/* Check if we are going to exceed the maximum PDU length. */
1742 	payload_len = ntohs(pdu->payload_len);
1743 	if ((payload_len + attr_tlv_len) > max_pdu_size) {
1744 		return (1);
1745 	}
1746 
1747 	attr_tlv = (isns_tlv_t *)kmem_zalloc(attr_tlv_len, KM_SLEEP);
1748 
1749 	attr_tlv->attr_id = htonl(attr_id);
1750 
1751 	switch (attr_id) {
1752 	case ISNS_DELIMITER_ATTR_ID:
1753 		break;
1754 
1755 	case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1756 	case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
1757 		if (attr_numeric_data == sizeof (in_addr_t)) {
1758 			/* IPv4 */
1759 			attr_tlv->attr_value[10] = 0xFF;
1760 			attr_tlv->attr_value[11] = 0xFF;
1761 			bcopy(attr_data, ((attr_tlv->attr_value) + 12),
1762 			    sizeof (in_addr_t));
1763 		} else if (attr_numeric_data == sizeof (in6_addr_t)) {
1764 			/* IPv6 */
1765 			bcopy(attr_data, attr_tlv->attr_value,
1766 			    sizeof (in6_addr_t));
1767 		} else if (attr_numeric_data == 0) {
1768 			/* EMPTY */
1769 			/* Do nothing */
1770 		} else {
1771 			kmem_free(attr_tlv, attr_tlv_len);
1772 			attr_tlv = NULL;
1773 			return (1);
1774 		}
1775 		break;
1776 
1777 	case ISNS_EID_ATTR_ID:
1778 	case ISNS_ISCSI_NAME_ATTR_ID:
1779 	case ISNS_ISCSI_ALIAS_ATTR_ID:
1780 	case ISNS_PG_ISCSI_NAME_ATTR_ID:
1781 		if (attr_len && attr_data) {
1782 			bcopy((char *)attr_data,
1783 			    attr_tlv->attr_value, attr_len);
1784 		}
1785 		break;
1786 
1787 	default:
1788 		if (attr_len == 8) {
1789 			*(uint64_t *)((void *)attr_tlv->attr_value) =
1790 			    BE_64((uint64_t)attr_numeric_data);
1791 		} else if (attr_len == 4) {
1792 			*(uint32_t *)((void *)attr_tlv->attr_value) =
1793 			    htonl((uint32_t)attr_numeric_data);
1794 		}
1795 		break;
1796 	}
1797 
1798 	attr_tlv->attr_len = htonl(normalized_attr_len);
1799 	/*
1800 	 * Convert the network byte ordered payload length to host byte
1801 	 * ordered for local address calculation.
1802 	 */
1803 	payload_len = ntohs(pdu->payload_len);
1804 	payload_ptr = pdu->payload + payload_len;
1805 	bcopy(attr_tlv, payload_ptr, attr_tlv_len);
1806 	payload_len += attr_tlv_len;
1807 
1808 	/*
1809 	 * Convert the host byte ordered payload length back to network
1810 	 * byte ordered - it's now ready to be sent on the wire.
1811 	 */
1812 	pdu->payload_len = htons(payload_len);
1813 
1814 	kmem_free(attr_tlv, attr_tlv_len);
1815 	attr_tlv = NULL;
1816 
1817 	return (0);
1818 }
1819 
1820 static void
1821 isnst_so_timeout(void *so)
1822 {
1823 	/* Wake up any sosend or sorecv blocked on this socket */
1824 	idm_soshutdown(so);
1825 }
1826 
1827 static int
1828 isnst_send_pdu(void *so, isns_pdu_t *pdu)
1829 {
1830 	size_t		total_len, payload_len, send_len;
1831 	uint8_t		*payload;
1832 	uint16_t	flags, seq;
1833 	timeout_id_t	send_timer;
1834 	iovec_t		iov[2];
1835 	int		rc;
1836 
1837 	/* update pdu flags */
1838 	flags  = ntohs(pdu->flags);
1839 	flags |= ISNS_FLAG_CLIENT;
1840 	flags |= ISNS_FLAG_FIRST_PDU;
1841 
1842 	/* initalize sequence number */
1843 	seq = 0;
1844 
1845 	payload = pdu->payload;
1846 
1847 	/* total payload length */
1848 	total_len = ntohs(pdu->payload_len);
1849 
1850 	/* fill in the pdu header */
1851 	iov[0].iov_base = (void *)pdu;
1852 	iov[0].iov_len = ISNSP_HEADER_SIZE;
1853 
1854 	do {
1855 		/* split the payload accordingly */
1856 		if (total_len > ISNSP_MAX_PAYLOAD_SIZE) {
1857 			payload_len = ISNSP_MAX_PAYLOAD_SIZE;
1858 		} else {
1859 			payload_len = total_len;
1860 			/* set the last pdu flag */
1861 			flags |= ISNS_FLAG_LAST_PDU;
1862 		}
1863 
1864 		/* set back the pdu flags */
1865 		pdu->flags = htons(flags);
1866 		/* set the sequence number */
1867 		pdu->seq = htons(seq);
1868 		/* set the payload length */
1869 		pdu->payload_len = htons(payload_len);
1870 
1871 		/* fill in the payload */
1872 		iov[1].iov_base = (void *)payload;
1873 		iov[1].iov_len = payload_len;
1874 
1875 		DTRACE_PROBE3(isnst__pdu__send, uint16_t, ntohs(pdu->func_id),
1876 		    uint16_t, ntohs(pdu->payload_len), caddr_t, pdu);
1877 
1878 		/* send the pdu */
1879 		send_len = ISNSP_HEADER_SIZE + payload_len;
1880 		send_timer = timeout(isnst_so_timeout, so,
1881 		    drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000));
1882 		rc = idm_iov_sosend(so, &iov[0], 2, send_len);
1883 		(void) untimeout(send_timer);
1884 
1885 		flags &= ~ISNS_FLAG_FIRST_PDU;
1886 		payload += payload_len;
1887 		total_len -= payload_len;
1888 
1889 		/* increase the sequence number */
1890 		seq ++;
1891 
1892 	} while (rc == 0 && total_len > 0);
1893 
1894 	return (rc);
1895 }
1896 
1897 static size_t
1898 isnst_rcv_pdu(void *so, isns_pdu_t **pdu)
1899 {
1900 	size_t		total_pdu_len;
1901 	size_t		total_payload_len;
1902 	size_t		payload_len;
1903 	size_t		combined_len;
1904 	isns_pdu_t	tmp_pdu_hdr;
1905 	isns_pdu_t	*combined_pdu;
1906 	uint8_t		*payload;
1907 	uint8_t		*combined_payload;
1908 	timeout_id_t	rcv_timer;
1909 	uint16_t	flags;
1910 	uint16_t	seq;
1911 
1912 	*pdu = NULL;
1913 	total_pdu_len = total_payload_len = 0;
1914 	payload = NULL;
1915 	seq = 0;
1916 
1917 	do {
1918 		/* receive the pdu header */
1919 		rcv_timer = timeout(isnst_so_timeout, so,
1920 		    drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000));
1921 		if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 ||
1922 		    ntohs(tmp_pdu_hdr.seq) != seq) {
1923 			(void) untimeout(rcv_timer);
1924 			goto rcv_error;
1925 		}
1926 		(void) untimeout(rcv_timer);
1927 
1928 		/* receive the payload */
1929 		payload_len = ntohs(tmp_pdu_hdr.payload_len);
1930 		payload = kmem_alloc(payload_len, KM_SLEEP);
1931 		rcv_timer = timeout(isnst_so_timeout, so,
1932 		    drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000));
1933 		if (idm_sorecv(so, payload, payload_len) != 0) {
1934 			(void) untimeout(rcv_timer);
1935 			goto rcv_error;
1936 		}
1937 		(void) untimeout(rcv_timer);
1938 
1939 		/* combine the pdu if it is not the first one */
1940 		if (total_pdu_len > 0) {
1941 			combined_len = total_pdu_len + payload_len;
1942 			combined_pdu = kmem_alloc(combined_len, KM_SLEEP);
1943 			bcopy(*pdu, combined_pdu, total_pdu_len);
1944 			combined_payload =
1945 			    &combined_pdu->payload[total_payload_len];
1946 			bcopy(payload, combined_payload, payload_len);
1947 			kmem_free(*pdu, total_pdu_len);
1948 			kmem_free(payload, payload_len);
1949 			*pdu = combined_pdu;
1950 			total_payload_len += payload_len;
1951 			total_pdu_len += payload_len;
1952 			(*pdu)->payload_len = htons(total_payload_len);
1953 		} else {
1954 			total_payload_len = payload_len;
1955 			total_pdu_len = ISNSP_HEADER_SIZE + payload_len;
1956 			*pdu = kmem_alloc(total_pdu_len, KM_SLEEP);
1957 			bcopy(&tmp_pdu_hdr, *pdu, ISNSP_HEADER_SIZE);
1958 			bcopy(payload, &(*pdu)->payload[0], payload_len);
1959 			kmem_free(payload, payload_len);
1960 		}
1961 		payload = NULL;
1962 
1963 		/* the flags of pdu which is just received */
1964 		flags = ntohs(tmp_pdu_hdr.flags);
1965 
1966 		/* increase sequence number by one */
1967 		seq ++;
1968 	} while ((flags & ISNS_FLAG_LAST_PDU) == 0);
1969 
1970 	DTRACE_PROBE3(isnst__pdu__recv, uint16_t, ntohs((*pdu)->func_id),
1971 	    size_t, total_payload_len, caddr_t, *pdu);
1972 
1973 	return (total_pdu_len);
1974 
1975 rcv_error:
1976 	if (*pdu != NULL) {
1977 		kmem_free(*pdu, total_pdu_len);
1978 		*pdu = NULL;
1979 	}
1980 	if (payload != NULL) {
1981 		kmem_free(payload, payload_len);
1982 	}
1983 	return (0);
1984 }
1985 
1986 static void *
1987 isnst_open_so(struct sockaddr_storage *sa)
1988 {
1989 	int sa_sz;
1990 	ksocket_t so;
1991 
1992 	/* determin local IP address */
1993 	if (sa->ss_family == AF_INET) {
1994 		/* IPv4 */
1995 		sa_sz = sizeof (struct sockaddr_in);
1996 
1997 		/* Create socket */
1998 		so = idm_socreate(AF_INET, SOCK_STREAM, 0);
1999 	} else {
2000 		/* IPv6 */
2001 		sa_sz = sizeof (struct sockaddr_in6);
2002 
2003 		/* Create socket */
2004 		so = idm_socreate(AF_INET6, SOCK_STREAM, 0);
2005 	}
2006 
2007 	if (so != NULL) {
2008 		if (ksocket_connect(so, (struct sockaddr *)sa, sa_sz, CRED())
2009 		    != 0) {
2010 			/* not calling isnst_close_so() to */
2011 			/* make dtrace output look clear */
2012 			idm_soshutdown(so);
2013 			idm_sodestroy(so);
2014 			so = NULL;
2015 		}
2016 	}
2017 
2018 	if (so == NULL) {
2019 		struct sockaddr_in *sin;
2020 		struct sockaddr_in6 *sin6;
2021 		char s[INET6_ADDRSTRLEN];
2022 		void *ip;
2023 		uint16_t port;
2024 		sin = (struct sockaddr_in *)sa;
2025 		port = ntohs(sin->sin_port);
2026 		if (sa->ss_family == AF_INET) {
2027 			ip = (void *)&sin->sin_addr.s_addr;
2028 			(void) inet_ntop(AF_INET, ip, s, sizeof (s));
2029 		} else {
2030 			sin6 = (struct sockaddr_in6 *)sa;
2031 			ip = (void *)&sin6->sin6_addr.s6_addr;
2032 			(void) inet_ntop(AF_INET6, ip, s, sizeof (s));
2033 		}
2034 		cmn_err(CE_WARN, "open iSNS Server %s:%u failed", s, port);
2035 	}
2036 
2037 	return (so);
2038 }
2039 
2040 static void
2041 isnst_close_so(void *so)
2042 {
2043 	idm_soshutdown(so);
2044 	idm_sodestroy(so);
2045 }
2046 
2047 
2048 /*
2049  * ESI handling
2050  */
2051 
2052 static void
2053 isnst_esi_start_thread(isns_esi_tinfo_t *tinfop)
2054 {
2055 	tinfop->esi_thread_running = B_FALSE;
2056 	tinfop->esi_thread_failed = B_FALSE;
2057 	tinfop->esi_registered = B_FALSE;
2058 	tinfop->esi_thread = thread_create(NULL, 0, isnst_esi_thread,
2059 	    (void *)tinfop, 0, &p0, TS_RUN, minclsyspri);
2060 
2061 	mutex_enter(&isns_esi_mutex);
2062 	list_insert_tail(&esi_list, tinfop);
2063 
2064 	/*
2065 	 * Wait for the thread to start
2066 	 */
2067 
2068 	while (!tinfop->esi_thread_running && !tinfop->esi_thread_failed) {
2069 		cv_wait(&isns_esi_cv, &isns_esi_mutex);
2070 	}
2071 
2072 	mutex_exit(&isns_esi_mutex);
2073 }
2074 
2075 static void
2076 isnst_esi_start(isns_portal_list_t *portal)
2077 {
2078 	isns_esi_tinfo_t	*tinfop;
2079 
2080 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
2081 
2082 	/*
2083 	 * Allocate our ESI thread info structure
2084 	 */
2085 
2086 	tinfop = (isns_esi_tinfo_t *)
2087 	    kmem_zalloc(sizeof (isns_esi_tinfo_t), KM_NOSLEEP);
2088 
2089 	if (tinfop == NULL) {
2090 		cmn_err(CE_WARN, "isnst_esi_start: Cant alloc ESI");
2091 		return;
2092 	}
2093 
2094 	tinfop->esi_portal = portal;
2095 	portal->portal_esi = tinfop;
2096 	isnst_esi_start_thread(tinfop);
2097 }
2098 
2099 /*
2100  * isnst_esi_check
2101  *
2102  * Verify that all the ESI threads are running and try to restart any that
2103  * failed for any reason.
2104  */
2105 
2106 static void
2107 isnst_esi_check()
2108 {
2109 	isns_portal_list_t	*portal;
2110 	isns_esi_tinfo_t	*tinfop;
2111 
2112 	/*
2113 	 * Now, threads for new portals or those which stopped for some other
2114 	 * reason will be started.
2115 	 */
2116 
2117 	portal = list_head(&portal_list);
2118 
2119 	while (portal) {
2120 		tinfop = portal->portal_esi;
2121 
2122 		if (tinfop && (!tinfop->esi_thread_running ||
2123 		    tinfop->esi_thread_failed)) {
2124 			isnst_esi_start_thread(tinfop);
2125 		}
2126 
2127 		portal = list_next(&portal_list, portal);
2128 	}
2129 }
2130 
2131 /*
2132  * isnst_esi_thread
2133  *
2134  * This function listens on a socket for incoming connections from an
2135  * iSNS server until told to stop.
2136  */
2137 
2138 static void
2139 isnst_esi_thread(void *arg)
2140 {
2141 	isns_esi_tinfo_t	*tinfop;
2142 	ksocket_t		newso;
2143 	struct sockaddr_in	sin;
2144 	struct sockaddr_in6	sin6;
2145 	uint32_t		on;
2146 	int			rc;
2147 	isns_pdu_t		*pdu;
2148 	size_t			pl_size;
2149 	int			family;
2150 	struct sockaddr_in	t_addr;
2151 	struct sockaddr_in6	t_addr6;
2152 	socklen_t		t_addrlen;
2153 	socklen_t		t_addrlen6;
2154 
2155 	bzero(&t_addr, sizeof (struct sockaddr_in6));
2156 	t_addrlen = sizeof (struct sockaddr_in);
2157 	t_addrlen6 = sizeof (struct sockaddr_in6);
2158 
2159 	tinfop = (isns_esi_tinfo_t *)arg;
2160 	tinfop->esi_thread_did = curthread->t_did;
2161 
2162 	/*
2163 	 * Create a socket to listen for requests from the iSNS server.
2164 	 */
2165 
2166 	if (tinfop->esi_portal->portal_addr.ss_family == AF_INET) {
2167 		family = AF_INET;
2168 	} else {
2169 		family = AF_INET6;
2170 	}
2171 
2172 	if ((tinfop->esi_so =
2173 	    idm_socreate(family, SOCK_STREAM, 0)) == NULL) {
2174 		cmn_err(CE_WARN,
2175 		    "isnst_esi_thread: Unable to create socket");
2176 		tinfop->esi_thread_failed = B_TRUE;
2177 		mutex_enter(&isns_esi_mutex);
2178 		cv_signal(&isns_esi_cv);
2179 		mutex_exit(&isns_esi_mutex);
2180 		thread_exit();
2181 	}
2182 	ksocket_hold(tinfop->esi_so);
2183 	/*
2184 	 * Set options, bind, and listen until we're told to stop
2185 	 */
2186 
2187 	switch (family) {
2188 	case AF_INET:
2189 		bzero(&sin, sizeof (sin));
2190 		sin.sin_family = AF_INET;
2191 		sin.sin_port = htons(0);
2192 		bcopy(((caddr_t)&tinfop->esi_portal->portal_addr +
2193 		    offsetof(struct sockaddr_in, sin_addr)),
2194 		    &sin.sin_addr.s_addr, sizeof (in_addr_t));
2195 		on = 1;
2196 
2197 		(void) ksocket_setsockopt(tinfop->esi_so, SOL_SOCKET,
2198 		    SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
2199 
2200 		if (ksocket_bind(tinfop->esi_so, (struct sockaddr *)&sin,
2201 		    sizeof (sin), CRED()) != 0) {
2202 			idm_sodestroy(tinfop->esi_so);
2203 			tinfop->esi_so = NULL;
2204 			tinfop->esi_thread_failed = B_TRUE;
2205 		} else {
2206 			(void) ksocket_getsockname(tinfop->esi_so,
2207 			    (struct sockaddr *)(&t_addr), &t_addrlen, CRED());
2208 			tinfop->esi_port = ntohs(((struct sockaddr_in *)
2209 			    (&t_addr))->sin_port);
2210 		}
2211 
2212 		break;
2213 
2214 	case AF_INET6:
2215 		bzero(&sin6, sizeof (sin6));
2216 		sin6.sin6_family = AF_INET6;
2217 		sin6.sin6_port = htons(0);
2218 		bcopy(((caddr_t)&tinfop->esi_portal->portal_addr +
2219 		    offsetof(struct sockaddr_in6, sin6_addr)),
2220 		    &sin6.sin6_addr.s6_addr, sizeof (in6_addr_t));
2221 		on = 1;
2222 
2223 		(void) ksocket_setsockopt(tinfop->esi_so, SOL_SOCKET,
2224 		    SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
2225 
2226 		if (ksocket_bind(tinfop->esi_so, (struct sockaddr *)&sin6,
2227 		    sizeof (sin6), CRED()) != 0) {
2228 			idm_sodestroy(tinfop->esi_so);
2229 			tinfop->esi_so = NULL;
2230 			tinfop->esi_thread_failed = B_TRUE;
2231 		} else {
2232 			(void) ksocket_getsockname(tinfop->esi_so,
2233 			    (struct sockaddr *)(&t_addr6), &t_addrlen6, CRED());
2234 			tinfop->esi_port = ntohs(((struct sockaddr_in6 *)
2235 			    (&t_addr6))->sin6_port);
2236 		}
2237 
2238 		break;
2239 	}
2240 
2241 	if (tinfop->esi_thread_failed) {
2242 		cmn_err(CE_WARN, "Unable to bind socket for ESI");
2243 		goto esi_thread_exit;
2244 	}
2245 
2246 	if ((rc = ksocket_listen(tinfop->esi_so, 5, CRED())) != 0) {
2247 		cmn_err(CE_WARN, "isnst_esi_thread: listen failure 0x%x", rc);
2248 		goto esi_thread_exit;
2249 	}
2250 
2251 	mutex_enter(&isns_esi_mutex);
2252 	/*
2253 	 * Mark the thread as running and the portal as no longer new.
2254 	 */
2255 	tinfop->esi_thread_running = B_TRUE;
2256 	cv_signal(&isns_esi_cv);
2257 
2258 	while (tinfop->esi_thread_running && !tinfop->esi_thread_failed) {
2259 		mutex_exit(&isns_esi_mutex);
2260 
2261 		DTRACE_PROBE2(iscsit__isns__esi__accept__wait,
2262 		    boolean_t, tinfop->esi_thread_running,
2263 		    boolean_t, tinfop->esi_thread_failed);
2264 		if ((rc = ksocket_accept(tinfop->esi_so, NULL, NULL,
2265 		    &newso, CRED())) != 0) {
2266 			mutex_enter(&isns_esi_mutex);
2267 			DTRACE_PROBE2(iscsit__isns__esi__accept__fail,
2268 			    boolean_t, tinfop->esi_thread_running,
2269 			    boolean_t, tinfop->esi_thread_failed);
2270 			/*
2271 			 * If we were interrupted with EINTR
2272 			 * it's not really a failure.
2273 			 */
2274 			if (rc != EINTR) {
2275 				cmn_err(CE_WARN, "isnst_esi_thread: "
2276 				    "accept failure (0x%x)", rc);
2277 				tinfop->esi_thread_failed = B_TRUE;
2278 			}
2279 			tinfop->esi_thread_running = B_FALSE;
2280 			continue;
2281 		}
2282 		DTRACE_PROBE3(iscsit__isns__esi__accept,
2283 		    boolean_t, tinfop->esi_thread_running,
2284 		    boolean_t, tinfop->esi_thread_failed,
2285 		    struct sonode *, newso);
2286 
2287 		mutex_enter(&isns_esi_mutex);
2288 
2289 		pl_size = isnst_rcv_pdu(newso, &pdu);
2290 
2291 		if (pl_size == 0) {
2292 			cmn_err(CE_WARN, "isnst_esi_thread: rcv_pdu failure");
2293 			tinfop->esi_thread_failed = B_TRUE;
2294 			continue;
2295 		}
2296 
2297 		if (isnst_handle_esi_req(newso, pdu, pl_size) == B_TRUE) {
2298 			tinfop->esi_registered = B_TRUE;
2299 		}
2300 
2301 		(void) ksocket_close(newso, CRED());
2302 
2303 		/*
2304 		 * Do not hold the esi mutex during server timestamp
2305 		 * update.  It requires the isns global lock, which may
2306 		 * be held during other functions that also require
2307 		 * the esi_mutex (potential deadlock).
2308 		 */
2309 		mutex_exit(&isns_esi_mutex);
2310 		isnst_update_server_timestamp(newso);
2311 		mutex_enter(&isns_esi_mutex);
2312 	}
2313 	mutex_exit(&isns_esi_mutex);
2314 esi_thread_exit:
2315 	ksocket_rele(tinfop->esi_so);
2316 	thread_exit();
2317 }
2318 
2319 /*
2320  * Handle an incoming ESI request
2321  */
2322 
2323 static boolean_t
2324 isnst_handle_esi_req(ksocket_t ks, isns_pdu_t *pdu, size_t pl_size)
2325 {
2326 	isns_pdu_t	*rsp_pdu;
2327 	isns_resp_t	*rsp;
2328 	size_t		pl_len, rsp_size;
2329 	boolean_t	esirv = B_TRUE;
2330 
2331 	if (ntohs(pdu->func_id) != ISNS_ESI) {
2332 		cmn_err(CE_WARN, "isnst_handle_esi_req: Unexpected func 0x%x",
2333 		    pdu->func_id);
2334 		kmem_free(pdu, pl_size);
2335 		return (B_FALSE);
2336 	}
2337 
2338 	pl_len = ntohs(pdu->payload_len) + 4 /* ISNS_STATUS_SZ */;
2339 
2340 	if (pl_len > ISNSP_MAX_PAYLOAD_SIZE) {
2341 		cmn_err(CE_WARN, "isnst_handle_esi_req: PDU payload too large "
2342 		    " (%ld bytes)", pl_len);
2343 		kmem_free(pdu, pl_size);
2344 		return (B_FALSE);
2345 	}
2346 
2347 	rsp_size = isnst_create_pdu_header(ISNS_ESI_RSP, &rsp_pdu, 0);
2348 
2349 	if (rsp_size == 0) {
2350 		cmn_err(CE_WARN, "isnst_handle_esi_req: Can't get rsp pdu");
2351 		kmem_free(pdu, pl_size);
2352 		return (B_FALSE);
2353 	}
2354 
2355 	rsp = (isns_resp_t *)((void *)(&rsp_pdu->payload[0]));
2356 
2357 	/* Use xid from the request pdu */
2358 	rsp_pdu->xid = pdu->xid;
2359 	rsp->status = htonl(ISNS_RSP_SUCCESSFUL);
2360 
2361 	/* Copy original data */
2362 	bcopy(pdu->payload, rsp->data, pl_len - 4);
2363 	rsp_pdu->payload_len = htons(pl_len);
2364 
2365 	if (isnst_send_pdu(ks, rsp_pdu) != 0) {
2366 		cmn_err(CE_WARN, "isnst_handle_esi_req: Send response failed");
2367 		esirv = B_FALSE;
2368 	}
2369 
2370 	kmem_free(rsp_pdu, rsp_size);
2371 	kmem_free(pdu, pl_size);
2372 
2373 	return (esirv);
2374 }
2375 
2376 int
2377 isnst_tgt_avl_compare(const void *t1, const void *t2)
2378 {
2379 	const isns_target_t	*tgt1 = t1;
2380 	const isns_target_t	*tgt2 = t2;
2381 
2382 	/*
2383 	 * Sort by target (pointer to iscsit_tgt_t).
2384 	 */
2385 
2386 	if (tgt1->target < tgt2->target) {
2387 		return (-1);
2388 	} else if (tgt1->target > tgt2->target) {
2389 		return (1);
2390 	}
2391 
2392 	return (0);
2393 }
2394 
2395 static void
2396 isnst_get_target_list(void)
2397 {
2398 	iscsit_tgt_t	*tgt, *next_tgt;
2399 
2400 	/*
2401 	 * Initialize our list of targets with those from the global
2402 	 * list that are online.
2403 	 */
2404 
2405 	for (tgt = avl_first(&iscsit_global.global_target_list); tgt != NULL;
2406 	    tgt = next_tgt) {
2407 		next_tgt = AVL_NEXT(&iscsit_global.global_target_list, tgt);
2408 		if (tgt->target_state == TS_STMF_ONLINE) {
2409 			(void) isnst_add_to_target_list(tgt);
2410 		}
2411 	}
2412 }
2413 
2414 static void
2415 isnst_set_server_status(iscsit_isns_svr_t *svr, boolean_t registered)
2416 {
2417 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
2418 
2419 	if (registered == B_TRUE) {
2420 		svr->svr_registered = B_TRUE;
2421 		svr->svr_last_msg = ddi_get_lbolt();
2422 	} else {
2423 		svr->svr_registered = B_FALSE;
2424 	}
2425 }
2426 
2427 static void
2428 isnst_add_default_portals()
2429 {
2430 	idm_addr_list_t		*default_portal_list;
2431 	idm_addr_t		*dportal;
2432 	isns_portal_list_t	*portal;
2433 	struct sockaddr_in	*sin;
2434 	struct sockaddr_in6	*sin6;
2435 	uint32_t		dpl_size, idx;
2436 
2437 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
2438 
2439 	dpl_size = idm_get_ipaddr(&default_portal_list);
2440 
2441 	if (dpl_size == 0) {
2442 		cmn_err(CE_WARN, "isnst_add_default_portals: "
2443 		    "No default portals");
2444 		return;
2445 	}
2446 
2447 	for (idx = 0; idx < default_portal_list->al_out_cnt; idx++) {
2448 		dportal = &default_portal_list->al_addrs[idx];
2449 
2450 		if (dportal->a_addr.i_insize == 0) {
2451 			continue;
2452 		}
2453 
2454 		portal = kmem_zalloc(sizeof (isns_portal_list_t), KM_SLEEP);
2455 		portal->portal_iscsit = NULL;	/* Default portal */
2456 
2457 		if (dportal->a_addr.i_insize == sizeof (struct in_addr)) {
2458 			sin = (struct sockaddr_in *)&portal->portal_addr;
2459 			sin->sin_family = AF_INET;
2460 			sin->sin_port = htons(ISCSI_LISTEN_PORT);
2461 			sin->sin_addr = dportal->a_addr.i_addr.in4;
2462 		} else {
2463 			sin6 = (struct sockaddr_in6 *)&portal->portal_addr;
2464 			sin->sin_family = AF_INET6;
2465 			sin6->sin6_port = htons(ISCSI_LISTEN_PORT);
2466 			sin6->sin6_addr = dportal->a_addr.i_addr.in6;
2467 		}
2468 
2469 		list_insert_tail(&portal_list, portal);
2470 		isnst_esi_start(portal);
2471 	}
2472 
2473 	kmem_free(default_portal_list, dpl_size);
2474 }
2475 
2476 static void
2477 isnst_remove_default_portals()
2478 {
2479 	isns_portal_list_t	*portal, *next;
2480 
2481 	ASSERT(ISNS_GLOBAL_LOCK_HELD());
2482 
2483 	portal = list_head(&portal_list);
2484 
2485 	while (portal) {
2486 		next = list_next(&portal_list, portal);
2487 
2488 		if (portal->portal_iscsit == NULL) {
2489 			mutex_enter(&isns_esi_mutex);
2490 			isnst_esi_stop_thread(portal->portal_esi);
2491 			mutex_exit(&isns_esi_mutex);
2492 			isns_remove_portal(portal);
2493 		}
2494 
2495 		portal = next;
2496 	}
2497 }
2498 
2499 /*
2500  * These functions are called by iscsit proper when a portal comes online
2501  * or goes offline.
2502  */
2503 
2504 void
2505 iscsit_isns_portal_online(iscsit_portal_t *portal)
2506 {
2507 	isns_portal_list_t	*iportal, *new_portal;
2508 	struct sockaddr_in	*sin;
2509 
2510 	ISNS_GLOBAL_LOCK();
2511 
2512 	iportal = isns_lookup_portal(&portal->portal_addr);
2513 	sin = (struct sockaddr_in *)&portal->portal_addr;
2514 
2515 	/*
2516 	 * If sin_family is 0, it's a "default" portal.  It's possible
2517 	 * sin_family may be non-zero, so check portal_iscsit.  If it's NULL,
2518 	 * it's a default portal as well.
2519 	 */
2520 
2521 	if ((sin->sin_family == 0) ||
2522 	    (iportal && (iportal->portal_iscsit == NULL))) {
2523 		ISNS_GLOBAL_UNLOCK();
2524 		return;
2525 	}
2526 
2527 	ASSERT(iportal == NULL);
2528 
2529 	new_portal = kmem_zalloc(sizeof (isns_portal_list_t), KM_SLEEP);
2530 	new_portal->portal_addr = portal->portal_addr;
2531 	sin = (struct sockaddr_in *)&new_portal->portal_addr;
2532 	new_portal->portal_iscsit = portal;
2533 	list_insert_tail(&portal_list, new_portal);
2534 	portal_list_count++;
2535 	nondefault_portals++;
2536 
2537 	ISNS_GLOBAL_UNLOCK();
2538 }
2539 
2540 void
2541 iscsit_isns_portal_offline(iscsit_portal_t *portal)
2542 {
2543 	isns_portal_list_t	*iportal = NULL;
2544 	struct sockaddr_in	*sin;
2545 	boolean_t		default_portals = B_FALSE;
2546 
2547 	ISNS_GLOBAL_LOCK();
2548 
2549 	/*
2550 	 * Stop the ESI thread for this portal
2551 	 */
2552 
2553 	iportal = isns_lookup_portal(&portal->portal_addr);
2554 	sin = (struct sockaddr_in *)&portal->portal_addr;
2555 
2556 	if ((sin->sin_family == 0) ||
2557 	    (iportal && (iportal->portal_iscsit == NULL))) {
2558 		default_portals = B_TRUE;
2559 	} else {
2560 		iportal = isns_lookup_portal(&portal->portal_addr);
2561 		ASSERT(iportal);
2562 	}
2563 
2564 	if (!default_portals) {
2565 		isns_remove_portal(iportal);
2566 		nondefault_portals--;
2567 	}
2568 
2569 	ISNS_GLOBAL_UNLOCK();
2570 }
2571