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