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.
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.
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]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/cpuvar.h>
26 #include <sys/types.h>
30 #include <sys/sunddi.h>
31 #include <sys/socket.h>
36 #include <sys/stmf_ioctl.h>
37 #include <sys/portif.h>
38 #include <sys/idm/idm.h>
39 #include <sys/idm/idm_so.h>
40 #include <sys/iscsit/iscsit_common.h>
41 #include <sys/iscsit/isns_protocol.h>
42 #include <sys/ksocket.h>
45 #include "iscsit_isns.h"
48 * iscsit_isns.c -- isns client that is part of the iscsit server
50 * The COMSTAR iSCSI target uses four pieces of iSNS functionality:
51 * - DevAttrReg to notify the iSNS server of our targets and portals.
52 * - DeregDev to notify when a target goes away or we shut down
53 * - DevAttrQry (self-query) to see if iSNS server still knows us.
54 * - Request ESI probes from iSNS server as a keepalive mechanism
56 * We send only two kinds of DevAttrReg messages.
58 * REPLACE-ALL the info the iSNS server knows about us:
59 * Set Flag in PDU header to ISNS_FLAG_REPLACE_REG
60 * Set "source" to same iSCSI target each time
61 * EID (Entity Identifier) == our DNS name
63 * Object operated on = EID
64 * "Entity Portals" owned by this "network entity"
66 * (Targets with TPGT are followed by PGT and PG portal info)
68 * UPDATE-EXISTING - used to register/change one target at a time
69 * Flag for replace reg not set
70 * Source and EID and Delimiter and Object Operated On as above
72 * (Targets with TPGT are followed by PGT and PG portal info)
74 * Interfaces to iscsit
76 * iscsit_isns_init -- called when iscsi/target service goes online
77 * iscsit_isns_fini -- called when iscsi/target service goes offline
78 * iscsit_isns_register -- a new target comes online
79 * iscsit_isns_deregister -- target goes offline
80 * iscsit_isns_target_update -- called when a target is modified
81 * iscsit_isns_portal_online -- called when defining a new portal
82 * iscsit_isns_portal_offline -- no longer using a portal
84 * Copying Data Structures
86 * The above routines copy all the data they need, so iscsit can
87 * proceed without interfering with us. This is moving in the
88 * direction of having this isns_client be a standalone user-mode
89 * program. Specifically, we copy the target name, alias, and
90 * tpgt+portal information.
92 * The iscsit_isns_mutex protects the shadow copies of target and portal
93 * information. The ISNS_GLOBAL_LOCK protects the iSNS run time structures
94 * that the monitor thread uses. The routine isnst_copy_global_status_changes
95 * has to acquire both locks and copy all the required information from the
96 * global structs to the per-server structs. Once it completes, the monitor
97 * thread should run completely off the per-server copies.
99 * Global State vs Per-Server state
100 * There is a global list of targets and portals that is kept updated
101 * by iscsit. Each svr keeps its own list of targets that have been
102 * announced to the iSNS server.
106 * 1) If svr->svr_registered, then there is some itarget with
107 * itarget->target_registered.
108 * 2) If itarget->target_delete_needed, then also itarget->target_registered.
109 * (Corollary: Any time you remove the last registered target, you have
110 * to send an unregister-all message.)
111 * 3) If a target has a non-default portal, then the portal goes online
112 * before the target goes online, and comes offline afterwards.
113 * (This is enforced by the iscsit state machines.)
116 #define MAX_XID (2^16)
117 #define ISNS_IDLE_TIME 60
118 #define MAX_RETRY (3)
119 #define ISNS_RCV_TIMER_SECONDS 5
121 #define VALID_NAME(NAME, LEN) \
122 ((LEN) > 0 && (NAME)[0] != 0 && (NAME)[(LEN) - 1] == 0)
125 #define ISNST_LOG if (iscsit_isns_logging) cmn_err
127 static kmutex_t isns_monitor_mutex
;
128 volatile kthread_t
*isns_monitor_thr_id
;
129 static kt_did_t isns_monitor_thr_did
;
130 static boolean_t isns_monitor_thr_running
;
132 static kcondvar_t isns_idle_cv
;
135 #define GET_XID() atomic_inc_16_nv(&xid)
137 static clock_t monitor_idle_interval
;
139 /* The ISNS_GLOBAL_LOCK protects the per-server data structures */
140 #define ISNS_GLOBAL_LOCK() \
141 mutex_enter(&iscsit_global.global_isns_cfg.isns_mutex)
143 #define ISNS_GLOBAL_LOCK_HELD() \
144 MUTEX_HELD(&iscsit_global.global_isns_cfg.isns_mutex)
146 #define ISNS_GLOBAL_UNLOCK() \
147 mutex_exit(&iscsit_global.global_isns_cfg.isns_mutex)
150 * "Configurable" parameters (set in /etc/system for now).
152 boolean_t iscsit_isns_logging
= B_FALSE
;
156 * If fail this many times to send an update to the server, then
157 * declare the server non-responsive and reregister everything with
158 * the server when we next connect.
160 int isns_max_retry
= MAX_RETRY
;
163 * The use of ESI probes to all active portals is not appropriate in
164 * all network environments, since the iSNS server may not have
165 * connectivity to all portals, so we turn it off by default.
167 boolean_t isns_use_esi
= B_FALSE
;
170 * Interval to request ESI probes at, in seconds. The server is free
171 * to specify a different frequency in its response.
173 int isns_default_esi_interval
= ISNS_DEFAULT_ESI_INTERVAL
;
177 * Registration Period -- we guarantee to check in with iSNS server at
178 * least this often. Used when ESI probes are turned off.
180 int isns_registration_period
= ISNS_DEFAULT_REGISTRATION_PERIOD
;
183 * Socket connect, PDU receive, and PDU send must complete
184 * within this number of microseconds.
186 uint32_t isns_timeout_usec
= ISNS_RCV_TIMER_SECONDS
* 1000000;
190 * iSNS Message size -- we start with the max that can fit into one PDU.
191 * If the message doesn't fit, we will expand at run time to a higher
192 * value. This parameter could be set in /etc/system if some particular
193 * installation knows it always goes over the standard limit.
195 uint32_t isns_message_buf_size
= ISNSP_MAX_PDU_SIZE
;
198 * Number of seconds to wait after isnst_monitor thread starts up
199 * before sending first DevAttrReg message.
201 int isns_initial_delay
= ISNS_INITIAL_DELAY
;
204 * Because of a bug in the Solaris isns server (c 2009), we cannot send a
205 * modify operation that changes the target's TPGTs. So just replace all.
206 * If the iSNS server does not have this bug, clear this flag.
207 * Changes take effect on each modify_target operation
209 boolean_t isns_modify_must_replace
= B_TRUE
;
211 /* If PDU sizes ever go over the following, we need to rearchitect */
212 #define ISNST_MAX_MSG_SIZE (16 * ISNSP_MAX_PDU_SIZE)
215 * iSNS ESI thread state
217 static isns_esi_tinfo_t esi
;
220 * Our list of targets. Kept in lock-step synch with iscsit.
221 * The iscsit_isns_mutex protects the global data structures that are
222 * kept in lock-step with iscsit.
223 * NOTE: Now that isnst runs independently of iscsit, we could remove the
224 * shadow copies of iscsit structures, such as isns_target_list and
225 * isns_tpg_portals, and have isnst_copy_global_status_changes reconcile
226 * isnst directly with the iscsit data structures.
228 static kmutex_t iscsit_isns_mutex
;
229 static avl_tree_t isns_target_list
;
230 static boolean_t isns_targets_changed
;
233 * List of portals from TPGs. Protected by iscsit_isns_mutex.
235 static boolean_t isns_portals_changed
;
236 static avl_tree_t isns_tpg_portals
;
237 static boolean_t default_portal_online
;
239 /* List of all portals. Protected by ISNS_GLOBAL_LOCK */
240 static avl_tree_t isns_all_portals
;
241 static int num_default_portals
;
242 static int num_tpg_portals
;
245 * Our entity identifier (fully-qualified hostname). Passed in from libiscsit.
247 static char *isns_eid
= NULL
;
250 * in6addr_any is currently all zeroes, but use the macro in case this
253 static const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
262 iscsit_set_isns(boolean_t state
);
265 iscsit_add_isns(it_portal_t
*cfg_svr
);
268 isnst_mark_delete_isns(iscsit_isns_svr_t
*svr
);
271 isnst_finish_delete_isns(iscsit_isns_svr_t
*svr
);
273 static iscsit_isns_svr_t
*
274 iscsit_isns_svr_lookup(struct sockaddr_storage
*sa
);
277 isnst_monitor(void *arg
);
280 isnst_monitor_one_server(iscsit_isns_svr_t
*svr
, boolean_t enabled
);
283 isnst_monitor_awaken(void);
286 isnst_update_server_timestamp(struct sockaddr_storage
*sa
);
289 isnst_copy_global_status_changes(void);
292 isnst_mark_deleted_targets(iscsit_isns_svr_t
*svr
);
295 isnst_update_one_server(iscsit_isns_svr_t
*svr
, isns_target_t
*target
,
296 isns_reg_type_t reg
);
298 static boolean_t
isnst_retry_registration(int rsp_status_code
);
300 static int isnst_register(iscsit_isns_svr_t
*svr
, isns_target_t
*itarget
,
301 isns_reg_type_t regtype
);
302 static int isnst_deregister(iscsit_isns_svr_t
*svr
, isns_target_t
*itarget
);
305 isnst_make_dereg_pdu(iscsit_isns_svr_t
*svr
, isns_pdu_t
**pdu
,
306 isns_target_t
*itarge
);
308 static int isnst_keepalive(iscsit_isns_svr_t
*svr
);
310 isnst_make_keepalive_pdu(iscsit_isns_svr_t
*svr
, isns_pdu_t
**pdu
);
312 static isns_target_t
*
313 isnst_get_registered_source(iscsit_isns_svr_t
*srv
);
314 static isns_target_t
*
315 isnst_get_registered_source_locked(iscsit_isns_svr_t
*srv
);
318 isnst_verify_rsp(iscsit_isns_svr_t
*svr
, isns_pdu_t
*pdu
,
319 isns_pdu_t
*rsp
, size_t rsp_size
);
322 isnst_pdu_get_op(isns_pdu_t
*pdu
, uint8_t **pp
);
325 isnst_make_reg_pdu(isns_pdu_t
**pdu
, isns_target_t
*target
,
326 iscsit_isns_svr_t
*svr
, isns_reg_type_t regtype
);
329 isnst_reg_pdu_add_entity_portals(isns_pdu_t
*pdu
, size_t pdu_size
);
332 isnst_reg_pdu_add_pg(isns_pdu_t
*pdu
, size_t pdu_size
, isns_target_t
*target
);
335 isnst_add_default_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
336 avl_tree_t
*null_portal_list
);
339 isnst_add_tpg_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
340 isns_tpgt_t
*tig
, avl_tree_t
*null_portal_list
);
343 isnst_add_null_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
344 avl_tree_t
*null_portal_list
);
347 isnst_add_portal_attr(isns_pdu_t
*pdu
, size_t pdu_size
,
348 uint32_t ip_attr_id
, uint32_t port_attr_id
,
349 struct sockaddr_storage
*ss
, boolean_t esi_info
);
352 isnst_create_pdu_header(uint16_t func_id
, isns_pdu_t
**pdu
, uint16_t flags
);
355 isnst_add_attr(isns_pdu_t
*pdu
,
360 uint32_t attr_numeric_data
);
363 isnst_send_pdu(void *so
, isns_pdu_t
*pdu
);
366 isnst_rcv_pdu(void *so
, isns_pdu_t
**pdu
);
369 isnst_open_so(struct sockaddr_storage
*sa
);
372 isnst_close_so(void *);
375 isnst_esi_thread(void *arg
);
378 isnst_handle_esi_req(ksocket_t so
, isns_pdu_t
*pdu
, size_t pl_size
);
380 static void isnst_esi_start(void);
381 static void isnst_esi_stop(void);
382 static isns_target_t
*isnst_latch_to_target_list(isns_target_t
*target
,
384 static void isnst_clear_target_list(iscsit_isns_svr_t
*svr
);
385 static void isnst_clear_from_target_list(isns_target_t
*target
,
386 avl_tree_t
*target_list
);
387 static int isnst_tgt_avl_compare(const void *t1
, const void *t2
);
388 static void isnst_set_server_status(iscsit_isns_svr_t
*svr
,
389 boolean_t registered
);
390 static void isnst_monitor_start(void);
391 static void isnst_monitor_stop(void);
394 isnst_monitor_default_portal_list(void);
397 isnst_find_default_portals(idm_addr_list_t
*alist
);
400 isnst_add_default_portals(idm_addr_list_t
*alist
);
403 isnst_clear_default_portals(void);
407 isnst_clear_portal_list(avl_tree_t
*portal_list
);
410 isnst_copy_portal_list(avl_tree_t
*t1
, avl_tree_t
*t2
);
412 static isns_portal_t
*
413 isnst_lookup_portal(struct sockaddr_storage
*sa
);
415 static isns_portal_t
*
416 isnst_add_to_portal_list(struct sockaddr_storage
*sa
, avl_tree_t
*portal_list
);
419 isnst_remove_from_portal_list(struct sockaddr_storage
*sa
,
420 avl_tree_t
*portal_list
);
423 isnst_portal_avl_compare(const void *t1
, const void *t2
);
431 isnst_config_merge(it_config_t
*cfg
)
433 boolean_t new_isns_state
= B_FALSE
;
434 iscsit_isns_svr_t
*isns_svr
, *next_isns_svr
;
435 it_portal_t
*cfg_isns_svr
;
440 * Determine whether iSNS is enabled in the new config.
441 * Isns property may not be set up yet.
443 (void) nvlist_lookup_boolean_value(cfg
->config_global_properties
,
444 PROP_ISNS_ENABLED
, &new_isns_state
);
446 /* Delete iSNS servers that are no longer part of the config */
447 for (isns_svr
= list_head(&iscsit_global
.global_isns_cfg
.isns_svrs
);
449 isns_svr
= next_isns_svr
) {
450 next_isns_svr
= list_next(
451 &iscsit_global
.global_isns_cfg
.isns_svrs
, isns_svr
);
452 if (it_sns_svr_lookup(cfg
, &isns_svr
->svr_sa
) == NULL
)
453 isnst_mark_delete_isns(isns_svr
);
456 /* Add new iSNS servers */
457 for (cfg_isns_svr
= cfg
->config_isns_svr_list
;
458 cfg_isns_svr
!= NULL
;
459 cfg_isns_svr
= cfg_isns_svr
->portal_next
) {
460 isns_svr
= iscsit_isns_svr_lookup(&cfg_isns_svr
->portal_addr
);
461 if (isns_svr
== NULL
) {
462 iscsit_add_isns(cfg_isns_svr
);
463 } else if (isns_svr
->svr_delete_needed
) {
465 * If reactivating a server that was being
466 * deleted, turn it into a reset.
468 isns_svr
->svr_delete_needed
= B_FALSE
;
469 isns_svr
->svr_reset_needed
= B_TRUE
;
474 * There is no "modify case" since the user specifies a complete
475 * server list each time. A modify is the same as a remove+add.
478 /* Start/Stop iSNS if necessary */
479 iscsit_set_isns(new_isns_state
);
481 ISNS_GLOBAL_UNLOCK();
484 /* Wake up the monitor thread to complete the state change */
485 isnst_monitor_awaken();
491 iscsit_isns_init(iscsit_hostinfo_t
*hostinfo
)
493 mutex_init(&iscsit_global
.global_isns_cfg
.isns_mutex
, NULL
,
494 MUTEX_DEFAULT
, NULL
);
497 mutex_init(&iscsit_isns_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
499 iscsit_global
.global_isns_cfg
.isns_state
= B_FALSE
;
500 list_create(&iscsit_global
.global_isns_cfg
.isns_svrs
,
501 sizeof (iscsit_isns_svr_t
), offsetof(iscsit_isns_svr_t
, svr_ln
));
502 avl_create(&isns_tpg_portals
, isnst_portal_avl_compare
,
503 sizeof (isns_portal_t
), offsetof(isns_portal_t
, portal_node
));
504 avl_create(&isns_all_portals
, isnst_portal_avl_compare
,
505 sizeof (isns_portal_t
), offsetof(isns_portal_t
, portal_node
));
506 num_default_portals
= 0;
507 if (hostinfo
->length
> ISCSIT_MAX_HOSTNAME_LEN
)
508 hostinfo
->length
= ISCSIT_MAX_HOSTNAME_LEN
;
509 isns_eid
= kmem_alloc(hostinfo
->length
, KM_SLEEP
);
510 (void) strlcpy(isns_eid
, hostinfo
->fqhn
, hostinfo
->length
);
511 avl_create(&isns_target_list
, isnst_tgt_avl_compare
,
512 sizeof (isns_target_t
), offsetof(isns_target_t
, target_node
));
514 /* initialize isns client */
515 mutex_init(&isns_monitor_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
516 mutex_init(&esi
.esi_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
517 isns_monitor_thr_id
= NULL
;
518 monitor_idle_interval
= ISNS_IDLE_TIME
* drv_usectohz(1000000);
519 cv_init(&isns_idle_cv
, NULL
, CV_DEFAULT
, NULL
);
520 cv_init(&esi
.esi_cv
, NULL
, CV_DEFAULT
, NULL
);
522 ISNS_GLOBAL_UNLOCK();
533 * The following call to iscsit_set_isns waits until all the
534 * iSNS servers have been fully deactivated and the monitor and esi
535 * threads have stopped.
537 iscsit_set_isns(B_FALSE
);
539 /* Clean up data structures */
540 mutex_destroy(&isns_monitor_mutex
);
541 cv_destroy(&isns_idle_cv
);
542 mutex_destroy(&esi
.esi_mutex
);
543 cv_destroy(&esi
.esi_cv
);
544 mutex_destroy(&iscsit_isns_mutex
);
547 * Free our EID and target list.
551 kmem_free(isns_eid
, strlen(isns_eid
) + 1);
555 iscsit_global
.global_isns_cfg
.isns_state
= B_FALSE
;
556 avl_destroy(&isns_target_list
);
557 list_destroy(&iscsit_global
.global_isns_cfg
.isns_svrs
);
558 avl_destroy(&isns_tpg_portals
);
559 avl_destroy(&isns_all_portals
);
560 num_default_portals
= 0;
561 ISNS_GLOBAL_UNLOCK();
563 mutex_destroy(&iscsit_global
.global_isns_cfg
.isns_mutex
);
567 iscsit_set_isns(boolean_t state
)
569 iscsit_isns_svr_t
*svr
;
571 ASSERT(ISNS_GLOBAL_LOCK_HELD());
574 * Update state and isns stop flag
576 if (iscsit_global
.global_isns_cfg
.isns_state
!= state
) {
577 /* reset retry count for all servers */
578 for (svr
= list_head(&iscsit_global
.global_isns_cfg
.isns_svrs
);
580 svr
= list_next(&iscsit_global
.global_isns_cfg
.isns_svrs
,
582 svr
->svr_retry_count
= 0;
585 iscsit_global
.global_isns_cfg
.isns_state
= state
;
596 iscsit_add_isns(it_portal_t
*cfg_svr
)
598 iscsit_isns_svr_t
*svr
;
600 ASSERT(ISNS_GLOBAL_LOCK_HELD());
602 svr
= kmem_zalloc(sizeof (iscsit_isns_svr_t
), KM_SLEEP
);
603 bcopy(&cfg_svr
->portal_addr
, &svr
->svr_sa
,
604 sizeof (struct sockaddr_storage
));
605 avl_create(&svr
->svr_target_list
, isnst_tgt_avl_compare
,
606 sizeof (isns_target_t
), offsetof(isns_target_t
, target_node
));
607 svr
->svr_esi_interval
= isns_default_esi_interval
;
609 /* put it on the global isns server list */
610 list_insert_tail(&iscsit_global
.global_isns_cfg
.isns_svrs
, svr
);
614 isnst_mark_delete_isns(iscsit_isns_svr_t
*svr
)
616 ASSERT(ISNS_GLOBAL_LOCK_HELD());
618 /* If monitor thread not running, finish delete here */
619 if (iscsit_global
.global_isns_cfg
.isns_state
== B_FALSE
) {
620 isnst_finish_delete_isns(svr
);
622 svr
->svr_delete_needed
= B_TRUE
;
628 isnst_finish_delete_isns(iscsit_isns_svr_t
*svr
)
631 ASSERT(ISNS_GLOBAL_LOCK_HELD());
632 isnst_clear_target_list(svr
);
634 list_remove(&iscsit_global
.global_isns_cfg
.isns_svrs
, svr
);
635 /* free the memory */
636 avl_destroy(&svr
->svr_target_list
);
637 kmem_free(svr
, sizeof (*svr
));
640 static iscsit_isns_svr_t
*
641 iscsit_isns_svr_lookup(struct sockaddr_storage
*sa
)
643 iscsit_isns_svr_t
*svr
;
646 ASSERT(ISNS_GLOBAL_LOCK_HELD());
648 bcopy(sa
, &portal1
.portal_addr
, sizeof (struct sockaddr_storage
));
650 for (svr
= list_head(&iscsit_global
.global_isns_cfg
.isns_svrs
);
652 svr
= list_next(&iscsit_global
.global_isns_cfg
.isns_svrs
, svr
)) {
653 if (it_sa_compare(&svr
->svr_sa
, sa
) == 0)
660 static isns_target_info_t
*
661 isnst_create_target_info(iscsit_tgt_t
*target
)
664 isns_target_info_t
*ti
;
666 isns_tpgt_addr_t
*tip
;
672 /* Cannot hold the iscsit_isns_mutex here! */
673 ASSERT(! mutex_owned(&iscsit_isns_mutex
));
675 ti
= kmem_zalloc(sizeof (isns_target_info_t
), KM_SLEEP
);
676 list_create(&ti
->ti_tpgt_list
,
677 sizeof (isns_tpgt_t
), offsetof(isns_tpgt_t
, ti_tpgt_ln
));
678 idm_refcnt_init(&ti
->ti_refcnt
, ti
);
680 mutex_enter(&target
->target_mutex
);
681 (void) strncpy(ti
->ti_tgt_name
, target
->target_name
,
682 MAX_ISCSI_NODENAMELEN
);
685 if (nvlist_lookup_string(target
->target_props
, PROP_ALIAS
,
687 (void) strncpy(ti
->ti_tgt_alias
, str
, MAX_ISCSI_NODENAMELEN
);
690 tpgt
= avl_first(&target
->target_tpgt_list
);
691 ASSERT(tpgt
!= NULL
);
693 tig
= kmem_zalloc(sizeof (isns_tpgt_t
), KM_SLEEP
);
694 list_create(&tig
->ti_portal_list
, sizeof (isns_tpgt_addr_t
),
695 offsetof(isns_tpgt_addr_t
, portal_ln
));
696 tig
->ti_tpgt_tag
= tpgt
->tpgt_tag
;
699 * Only need portal list for non-default portal.
701 if (tpgt
->tpgt_tag
!= ISCSIT_DEFAULT_TPGT
) {
702 tpg
= tpgt
->tpgt_tpg
;
704 mutex_enter(&tpg
->tpg_mutex
);
706 tp
= avl_first(&tpg
->tpg_portal_list
);
708 tip
= kmem_zalloc(sizeof (isns_tpgt_addr_t
),
710 bcopy(&tp
->portal_addr
, &tip
->portal_addr
,
711 sizeof (tip
->portal_addr
));
712 list_insert_tail(&tig
->ti_portal_list
, tip
);
714 tp
= AVL_NEXT(&tpg
->tpg_portal_list
, tp
);
715 } while (tp
!= NULL
);
716 mutex_exit(&tpg
->tpg_mutex
);
718 list_insert_tail(&ti
->ti_tpgt_list
, tig
);
719 tpgt
= AVL_NEXT(&target
->target_tpgt_list
, tpgt
);
720 } while (tpgt
!= NULL
);
721 mutex_exit(&target
->target_mutex
);
727 isnst_clear_target_info_cb(void *arg
)
729 isns_target_info_t
*ti
= (isns_target_info_t
*)arg
;
731 isns_tpgt_addr_t
*tip
;
733 while ((tig
= list_remove_head(&ti
->ti_tpgt_list
)) != NULL
) {
734 while ((tip
= list_remove_head(&tig
->ti_portal_list
)) != NULL
) {
735 kmem_free(tip
, sizeof (isns_tpgt_addr_t
));
737 list_destroy(&tig
->ti_portal_list
);
738 kmem_free(tig
, sizeof (isns_tpgt_t
));
740 list_destroy(&ti
->ti_tpgt_list
);
741 idm_refcnt_destroy(&ti
->ti_refcnt
);
742 kmem_free(ti
, sizeof (isns_target_info_t
));
747 * iscsit_isns_register
748 * called by iscsit when a target goes online
751 iscsit_isns_register(iscsit_tgt_t
*target
)
753 isns_target_t
*itarget
, tmptgt
;
755 isns_target_info_t
*ti
;
757 /* Create TI struct outside of isns_mutex */
758 ti
= isnst_create_target_info(target
);
760 mutex_enter(&iscsit_isns_mutex
);
762 tmptgt
.target
= target
;
763 if ((itarget
= (isns_target_t
*)avl_find(&isns_target_list
,
764 &tmptgt
, &where
)) == NULL
) {
765 itarget
= kmem_zalloc(sizeof (isns_target_t
), KM_SLEEP
);
767 itarget
->target
= target
;
768 avl_insert(&isns_target_list
, (void *)itarget
, where
);
773 /* Copy the target info so it will last beyond deregister */
774 itarget
->target_info
= ti
;
775 idm_refcnt_hold(&ti
->ti_refcnt
);
777 isns_targets_changed
= B_TRUE
;
779 mutex_exit(&iscsit_isns_mutex
);
781 isnst_monitor_awaken();
786 * iscsit_isns_deregister
787 * called by iscsit when a target goes offline
790 iscsit_isns_deregister(iscsit_tgt_t
*target
)
792 isns_target_t
*itarget
, tmptgt
;
793 isns_target_info_t
*ti
;
795 tmptgt
.target
= target
;
797 mutex_enter(&iscsit_isns_mutex
);
799 itarget
= avl_find(&isns_target_list
, &tmptgt
, NULL
);
800 ASSERT(itarget
!= NULL
);
801 ti
= itarget
->target_info
;
804 * The main thread is done with the target_info object.
805 * Make sure the delete callback is called when
806 * all the svrs are done with it.
808 idm_refcnt_rele(&ti
->ti_refcnt
);
809 idm_refcnt_async_wait_ref(&ti
->ti_refcnt
,
810 (idm_refcnt_cb_t
*)&isnst_clear_target_info_cb
);
812 itarget
->target_info
= NULL
;
813 avl_remove(&isns_target_list
, itarget
);
814 kmem_free(itarget
, sizeof (isns_target_t
));
816 isns_targets_changed
= B_TRUE
;
818 mutex_exit(&iscsit_isns_mutex
);
820 isnst_monitor_awaken();
825 * iscsit_isns_target_update
826 * This function is called by iscsit when a target's configuration
831 iscsit_isns_target_update(iscsit_tgt_t
*target
)
833 isns_target_t
*itarget
, tmptgt
;
834 isns_target_info_t
*ti
;
836 /* Create new TI struct outside of isns_mutex */
837 ti
= isnst_create_target_info(target
);
839 mutex_enter(&iscsit_isns_mutex
);
842 * If iscsit calls us to modify a target, that target should
843 * already exist in the isns_svr_list.
845 tmptgt
.target
= target
;
846 itarget
= avl_find(&isns_target_list
, &tmptgt
, NULL
);
847 if (itarget
== NULL
) {
849 * If target-update gets called while the target is still
850 * offline, then there is nothing to do. The target will be
851 * completely registered when it comes online.
853 mutex_exit(&iscsit_isns_mutex
);
854 /* Remove the target_info struct -- not needed */
855 isnst_clear_target_info_cb(ti
);
859 /* Remove the old target_info struct */
860 idm_refcnt_rele(&itarget
->target_info
->ti_refcnt
);
861 idm_refcnt_async_wait_ref(&itarget
->target_info
->ti_refcnt
,
862 (idm_refcnt_cb_t
*)&isnst_clear_target_info_cb
);
864 /* Link to new target_info struct */
865 itarget
->target_info
= ti
;
866 idm_refcnt_hold(&ti
->ti_refcnt
);
868 itarget
->target_update_needed
= B_TRUE
;
870 isns_targets_changed
= B_TRUE
;
872 mutex_exit(&iscsit_isns_mutex
);
874 isnst_monitor_awaken();
880 ISNST_LOG(CE_NOTE
, "**** isnst_start");
882 ASSERT(ISNS_GLOBAL_LOCK_HELD());
885 * Start ESI thread(s)
890 * Create a thread for monitoring server communications
892 isnst_monitor_start();
898 ASSERT(ISNS_GLOBAL_LOCK_HELD());
899 ISNST_LOG(CE_NOTE
, "**** isnst_stop");
902 ISNS_GLOBAL_UNLOCK();
904 isnst_monitor_stop();
909 isnst_monitor_start(void)
911 ISNST_LOG(CE_NOTE
, "isnst_monitor_start");
914 mutex_enter(&isns_monitor_mutex
);
915 ASSERT(!isns_monitor_thr_running
);
916 isns_monitor_thr_id
= thread_create(NULL
, 0,
917 isnst_monitor
, NULL
, 0, &p0
, TS_RUN
, minclsyspri
);
918 while (!isns_monitor_thr_running
)
919 cv_wait(&isns_idle_cv
, &isns_monitor_mutex
);
920 mutex_exit(&isns_monitor_mutex
);
924 isnst_monitor_stop(void)
926 ISNST_LOG(CE_NOTE
, "isnst_monitor_stop");
928 mutex_enter(&isns_monitor_mutex
);
929 if (isns_monitor_thr_running
) {
930 isns_monitor_thr_running
= B_FALSE
;
931 cv_signal(&isns_idle_cv
);
932 mutex_exit(&isns_monitor_mutex
);
934 thread_join(isns_monitor_thr_did
);
937 mutex_exit(&isns_monitor_mutex
);
941 * isnst_update_server_timestamp
943 * When we receive an ESI request, update the timestamp for the server.
944 * If we don't receive one for the specified period of time, we'll attempt
949 isnst_update_server_timestamp(struct sockaddr_storage
*ss
)
951 iscsit_isns_svr_t
*svr
;
953 ASSERT(ISNS_GLOBAL_LOCK_HELD());
956 * Find the server and update the timestamp
958 for (svr
= list_head(&iscsit_global
.global_isns_cfg
.isns_svrs
);
960 svr
= list_next(&iscsit_global
.global_isns_cfg
.isns_svrs
, svr
)) {
962 * Note that the port number in incoming probe will be
963 * different than the iSNS server's port number.
965 if (idm_ss_compare(ss
, &svr
->svr_sa
,
966 B_TRUE
/* v4_mapped_as_v4 */,
967 B_FALSE
/* don't compare_ports */) == 0) {
973 /* Update the timestamp we keep for this server */
974 svr
->svr_last_msg
= ddi_get_lbolt();
976 * If we receive ESI probe from a server we are not
977 * registered to, then cause a re-reg attempt.
979 if (!svr
->svr_registered
) {
980 isnst_monitor_awaken();
990 * isnst_monitor_all_servers -- loop through all servers
995 isnst_monitor_all_servers()
997 iscsit_isns_svr_t
*svr
, *next_svr
;
1002 svr_list
= &iscsit_global
.global_isns_cfg
.isns_svrs
;
1006 isnst_copy_global_status_changes();
1008 enabled
= iscsit_global
.global_isns_cfg
.isns_state
;
1009 for (svr
= list_head(svr_list
); svr
!= NULL
; svr
= next_svr
) {
1011 svr
->svr_monitor_hold
= B_TRUE
;
1013 * isnst_monitor_one_server can release ISNS_GLOBAL_LOCK
1014 * internally. This allows isnst_config_merge to run
1015 * even when messages to iSNS servers are pending.
1017 rc
= isnst_monitor_one_server(svr
, enabled
);
1019 svr
->svr_retry_count
++;
1020 if (svr
->svr_registered
&&
1021 svr
->svr_retry_count
> isns_max_retry
) {
1022 char server_buf
[IDM_SA_NTOP_BUFSIZ
];
1024 if (! svr
->svr_reset_needed
) {
1026 "isnst: iSNS server %s"
1027 " not responding (rc=%d).",
1028 idm_sa_ntop(&svr
->svr_sa
,
1029 server_buf
, sizeof (server_buf
)),
1031 svr
->svr_reset_needed
= B_TRUE
;
1035 svr
->svr_retry_count
= 0;
1038 * If we have finished unregistering this server,
1039 * it is now OK to delete it.
1041 svr
->svr_monitor_hold
= B_FALSE
;
1042 next_svr
= list_next(svr_list
, svr
);
1043 if (svr
->svr_delete_needed
== B_TRUE
&&
1044 svr
->svr_registered
== B_FALSE
) {
1045 isnst_finish_delete_isns(svr
);
1048 ISNS_GLOBAL_UNLOCK();
1052 isnst_monitor_awaken(void)
1054 mutex_enter(&isns_monitor_mutex
);
1055 if (isns_monitor_thr_running
) {
1056 DTRACE_PROBE(iscsit__isns__monitor__awaken
);
1057 cv_signal(&isns_idle_cv
);
1059 mutex_exit(&isns_monitor_mutex
);
1063 * isnst_monitor -- the monitor thread for iSNS
1067 isnst_monitor(void *arg
)
1069 mutex_enter(&isns_monitor_mutex
);
1070 isns_monitor_thr_did
= curthread
->t_did
;
1071 isns_monitor_thr_running
= B_TRUE
;
1072 cv_signal(&isns_idle_cv
);
1075 * Start with a short pause (5 sec) to allow all targets
1076 * to be registered before we send register-all. This is
1077 * purely an optimization to cut down on the number of
1078 * messages we send to the iSNS server.
1080 mutex_exit(&isns_monitor_mutex
);
1081 ddi_sleep(isns_initial_delay
);
1082 mutex_enter(&isns_monitor_mutex
);
1084 /* Force an initialization of isns_all_portals */
1085 mutex_enter(&iscsit_isns_mutex
);
1086 isns_portals_changed
= B_TRUE
;
1087 mutex_exit(&iscsit_isns_mutex
);
1089 while (isns_monitor_thr_running
) {
1091 /* Update servers */
1092 mutex_exit(&isns_monitor_mutex
);
1093 isnst_monitor_all_servers();
1094 mutex_enter(&isns_monitor_mutex
);
1096 /* If something needs attention, go right to the top */
1097 mutex_enter(&iscsit_isns_mutex
);
1098 if (isns_targets_changed
|| isns_portals_changed
) {
1099 DTRACE_PROBE(iscsit__isns__monitor__reenter
);
1100 mutex_exit(&iscsit_isns_mutex
);
1101 /* isns_monitor_mutex still held */
1104 mutex_exit(&iscsit_isns_mutex
);
1107 * Keep running until isns_monitor_thr_running is set to
1110 if (! isns_monitor_thr_running
)
1113 DTRACE_PROBE(iscsit__isns__monitor__sleep
);
1114 (void) cv_reltimedwait(&isns_idle_cv
, &isns_monitor_mutex
,
1115 monitor_idle_interval
, TR_CLOCK_TICK
);
1116 DTRACE_PROBE1(iscsit__isns__monitor__wakeup
,
1117 boolean_t
, isns_monitor_thr_running
);
1120 mutex_exit(&isns_monitor_mutex
);
1122 /* Update the servers one last time for deregistration */
1123 isnst_monitor_all_servers();
1125 /* Clean up the all-portals list */
1127 isnst_clear_default_portals();
1128 ISNS_GLOBAL_UNLOCK();
1130 /* terminate the thread at the last */
1135 isnst_monitor_one_server(iscsit_isns_svr_t
*svr
, boolean_t enabled
)
1138 isns_target_t
*itarget
;
1140 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1143 * First, take care of the case where iSNS is no longer enabled.
1147 if (enabled
== B_FALSE
|| svr
->svr_delete_needed
) {
1149 * Just try one time to deregister all from server.
1150 * Doesn't matter if this fails. We're disabled.
1152 (void) isnst_update_one_server(svr
, NULL
, ISNS_DEREGISTER_ALL
);
1153 isnst_set_server_status(svr
, B_FALSE
);
1159 * If the server needs replace-all, check if it should
1160 * be a DevDereg (i.e. if the last target is gone.)
1163 if (svr
->svr_registered
&& svr
->svr_reset_needed
) {
1164 /* Send DevDereg if last registered target */
1165 isns_target_t
*jtarget
;
1166 for (jtarget
= avl_first(&svr
->svr_target_list
);
1168 jtarget
= AVL_NEXT(&svr
->svr_target_list
, jtarget
)) {
1169 if (!jtarget
->target_delete_needed
) {
1174 * jtarget is null IFF all tgts need deletion,
1175 * and there are no new targets to register.
1177 if (jtarget
== NULL
) {
1178 rc
= isnst_update_one_server(svr
, NULL
,
1179 ISNS_DEREGISTER_ALL
);
1183 isnst_set_server_status(svr
, B_FALSE
);
1189 * If the server is not yet registered, do the registration
1191 if (! svr
->svr_registered
|| svr
->svr_reset_needed
) {
1193 if (avl_numnodes(&svr
->svr_target_list
) == 0) {
1194 /* If no targets, nothing to register */
1197 if ((rc
= isnst_update_one_server(svr
, NULL
,
1198 ISNS_REGISTER_ALL
)) != 0) {
1199 /* Registration failed */
1202 isnst_set_server_status(svr
, B_TRUE
);
1206 /* The following checks are expensive, so only do them if needed */
1207 if (svr
->svr_targets_changed
) {
1208 isns_target_t
*next_target
;
1210 * If there is a target to be deleted, send the
1211 * deletion request for one target at a time.
1213 for (itarget
= avl_first(&svr
->svr_target_list
);
1215 itarget
= next_target
) {
1216 next_target
= AVL_NEXT(&svr
->svr_target_list
, itarget
);
1217 if (itarget
->target_delete_needed
) {
1218 /* See if last non-deleted target */
1219 isns_target_t
*jtarget
;
1220 ASSERT(itarget
->target_registered
);
1222 avl_first(&svr
->svr_target_list
);
1224 jtarget
= AVL_NEXT(&svr
->svr_target_list
,
1226 if (jtarget
->target_registered
&&
1227 !jtarget
->target_delete_needed
) {
1231 /* jtarget is null if last registered tgt */
1232 if (jtarget
== NULL
) {
1234 * Removing last tgt -- deregister all.
1235 * Doesn't matter if this fails.
1238 rc
= isnst_update_one_server(svr
,
1239 NULL
, ISNS_DEREGISTER_ALL
);
1243 isnst_set_server_status(svr
, B_FALSE
);
1246 rc
= isnst_update_one_server(svr
,
1247 itarget
, ISNS_DEREGISTER_TARGET
);
1248 if (rc
!= 0 && isnst_retry_registration(rc
)) {
1249 /* Retryable code => try replace-all */
1250 svr
->svr_reset_needed
= B_TRUE
;
1251 goto retry_replace_all
;
1257 isnst_clear_from_target_list(itarget
,
1258 &svr
->svr_target_list
);
1262 /* If any target needs a register or an update, do so */
1263 itarget
= avl_first(&svr
->svr_target_list
);
1265 if (!itarget
->target_registered
||
1266 itarget
->target_update_needed
) {
1269 * Because of a bug in the isns
1270 * server, we cannot send a modify
1271 * operation that changes the target's
1272 * TPGTs. So just replace all.
1274 if (isns_modify_must_replace
) {
1275 svr
->svr_reset_needed
= B_TRUE
;
1276 goto retry_replace_all
;
1278 /* Try to update existing info for one tgt */
1279 rc
= isnst_update_one_server(svr
,
1281 ISNS_MODIFY_TARGET
);
1282 if (rc
!= 0 && isnst_retry_registration(rc
)) {
1283 /* Retryable code => try replace-all */
1284 svr
->svr_reset_needed
= B_TRUE
;
1285 goto retry_replace_all
;
1290 itarget
->target_update_needed
=
1292 itarget
->target_registered
= B_TRUE
;
1294 itarget
= AVL_NEXT(&svr
->svr_target_list
,
1299 * We have gone through all the cases -- this server
1300 * is now up to date.
1302 svr
->svr_targets_changed
= B_FALSE
;
1308 * If using ESI, and no ESI request is received within
1309 * MAX_ESI_INTERVALS (3) number of intervals, we'll
1310 * try to re-register with the server. The server will
1311 * delete our information if we fail to respond for 2
1314 if (ddi_get_lbolt() >= (svr
->svr_last_msg
+
1315 drv_usectohz(svr
->svr_esi_interval
* 1000000 *
1316 MAX_ESI_INTERVALS
))) {
1317 /* re-register everything */
1318 svr
->svr_reset_needed
= B_TRUE
;
1319 goto retry_replace_all
;
1323 * If not using ESI, make sure to ping server during
1324 * each registration period. Do this at half the
1325 * registration interval, so we won't get timed out.
1327 if (ddi_get_lbolt() >= (svr
->svr_last_msg
+
1328 drv_usectohz(isns_registration_period
* (1000000/3)))) {
1329 /* Send a self-query as a keepalive. */
1330 ISNS_GLOBAL_UNLOCK();
1331 rc
= isnst_keepalive(svr
);
1333 if (rc
!= 0 && isnst_retry_registration(rc
)) {
1334 /* Retryable code => try replace-all */
1335 svr
->svr_reset_needed
= B_TRUE
;
1336 goto retry_replace_all
;
1348 * isnst_mark_deleted_target -- find tgt in svr list but not global list
1351 isnst_mark_deleted_targets(iscsit_isns_svr_t
*svr
)
1353 isns_target_t
*itarget
, *nxt_target
, tmptgt
;
1355 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1356 ASSERT(mutex_owned(&iscsit_isns_mutex
));
1358 for (itarget
= avl_first(&svr
->svr_target_list
);
1360 itarget
= nxt_target
) {
1361 tmptgt
.target
= itarget
->target
;
1362 nxt_target
= AVL_NEXT(&svr
->svr_target_list
, itarget
);
1363 if (avl_find(&isns_target_list
, &tmptgt
, NULL
) == NULL
) {
1364 if (itarget
->target_registered
) {
1365 itarget
->target_delete_needed
= B_TRUE
;
1367 isnst_clear_from_target_list(itarget
,
1368 &svr
->svr_target_list
);
1374 static isns_target_t
*
1375 isnst_latch_to_target_list(isns_target_t
*jtarget
, avl_tree_t
*target_list
)
1377 isns_target_t
*itarget
, tmptgt
;
1380 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1381 ASSERT(mutex_owned(&iscsit_isns_mutex
));
1383 * Make sure this target isn't already in our list.
1386 tmptgt
.target
= jtarget
->target
;
1387 if ((itarget
= (isns_target_t
*)avl_find(target_list
,
1388 &tmptgt
, &where
)) == NULL
) {
1389 itarget
= kmem_zalloc(sizeof (isns_target_t
), KM_SLEEP
);
1391 itarget
->target
= jtarget
->target
;
1392 itarget
->target_info
= jtarget
->target_info
;
1393 idm_refcnt_hold(&itarget
->target_info
->ti_refcnt
);
1395 avl_insert(target_list
, (void *)itarget
, where
);
1404 isnst_clear_target_list(iscsit_isns_svr_t
*svr
)
1406 isns_target_t
*itarget
;
1408 while ((itarget
= avl_first(&svr
->svr_target_list
)) != NULL
) {
1409 isnst_clear_from_target_list(itarget
,
1410 &svr
->svr_target_list
);
1415 isnst_clear_from_target_list(isns_target_t
*jtarget
, avl_tree_t
*target_list
)
1417 isns_target_t
*itarget
, tmptgt
;
1419 tmptgt
.target
= jtarget
->target
;
1421 if ((itarget
= avl_find(target_list
, &tmptgt
, NULL
))
1424 avl_remove(target_list
, itarget
);
1425 idm_refcnt_rele(&itarget
->target_info
->ti_refcnt
);
1426 kmem_free(itarget
, sizeof (isns_target_t
));
1433 * isnst_copy_global_status_changes -- update svrs to match iscsit
1435 * At the end of this routine svr->svr_target_list has all the entries
1436 * in the current isns_target_list plus any targets that are marked
1440 isnst_copy_global_status_changes(void)
1442 isns_target_t
*ttarget
, *itarget
, tmptgt
;
1443 iscsit_isns_svr_t
*svr
;
1445 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1448 * Copy info about recent transitions from global state to
1449 * per-server state. We use the global state so that iscsit
1450 * functions can proceed without blocking on slow-to-release
1453 mutex_enter(&iscsit_isns_mutex
);
1456 * Periodically check for changed IP addresses. This function
1457 * sets isns_all_portals to the current set, and sets
1458 * isns_portals_changed if a portal is added or removed.
1460 isnst_monitor_default_portal_list();
1462 /* Initialize the per-server structs to some basic values */
1463 for (svr
= list_head(&iscsit_global
.global_isns_cfg
.isns_svrs
);
1465 svr
= list_next(&iscsit_global
.global_isns_cfg
.isns_svrs
,
1467 if (isns_portals_changed
&& svr
->svr_registered
) {
1469 * Cause re-register, for now, when portals change.
1470 * Eventually, we should add new portals one by one
1472 svr
->svr_reset_needed
= B_TRUE
;
1474 if (!svr
->svr_registered
) {
1475 /* To re-register, start with empty target list */
1476 isnst_clear_target_list(svr
);
1477 /* And set flag to add all current targets, below */
1478 isns_targets_changed
= B_TRUE
;
1479 } else if (isns_targets_changed
|| svr
->svr_reset_needed
) {
1480 /* Mark to look for target changes */
1481 isnst_mark_deleted_targets(svr
);
1482 svr
->svr_targets_changed
= B_TRUE
;
1487 * If any target has been modified, tell all the svrs to
1488 * update that target.
1490 if (isns_targets_changed
) {
1491 ttarget
= avl_first(&isns_target_list
);
1493 for (svr
= list_head(
1494 &iscsit_global
.global_isns_cfg
.isns_svrs
);
1497 &iscsit_global
.global_isns_cfg
.isns_svrs
,
1499 tmptgt
.target
= ttarget
->target
;
1501 &svr
->svr_target_list
,
1504 if (itarget
== NULL
) {
1505 /* Add a new target */
1506 (void) isnst_latch_to_target_list(
1507 ttarget
, &svr
->svr_target_list
);
1508 } else if (ttarget
->target_update_needed
) {
1509 /* Modify existing target */
1510 itarget
->target_update_needed
=
1512 /* Remove link to old target_info */
1514 &itarget
->target_info
->ti_refcnt
);
1515 /* Link to new target_info struct */
1516 itarget
->target_info
=
1517 ttarget
->target_info
;
1519 &itarget
->target_info
->ti_refcnt
);
1522 ttarget
->target_update_needed
= B_FALSE
;
1523 ttarget
= AVL_NEXT(&isns_target_list
, ttarget
);
1528 * Now we have updated the per-server state for all servers.
1529 * Clear the global state flags
1531 isns_targets_changed
= B_FALSE
;
1532 isns_portals_changed
= B_FALSE
;
1533 mutex_exit(&iscsit_isns_mutex
);
1537 * isnst_update_one_server releases ISNS_GLOBAL_LOCK internally and
1538 * acquires it again as needed. This allows isnst_config_merge and
1539 * isnst_esi_thread to run even while waiting for a response from the
1540 * iSNS server (or a dead iSNS server).
1543 isnst_update_one_server(iscsit_isns_svr_t
*svr
, isns_target_t
*itarget
,
1544 isns_reg_type_t reg
)
1548 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1549 ISNS_GLOBAL_UNLOCK();
1552 case ISNS_DEREGISTER_TARGET
:
1553 rc
= isnst_deregister(svr
, itarget
);
1556 case ISNS_DEREGISTER_ALL
:
1557 rc
= isnst_deregister(svr
, NULL
);
1560 case ISNS_MODIFY_TARGET
:
1561 case ISNS_REGISTER_TARGET
:
1562 rc
= isnst_register(svr
, itarget
, reg
);
1565 case ISNS_REGISTER_ALL
:
1566 rc
= isnst_register(svr
, NULL
, reg
);
1579 * isnst_retry_registration
1581 * This function checks the return value from a registration pdu and
1582 * determines whether or not we should retry this request. If the
1583 * request is retried, it will do so as an "update", which means we
1584 * re-register everything.
1588 isnst_retry_registration(int rsp_status_code
)
1593 * The following are the error codes that indicate isns-client
1594 * and isns-server are out of synch. E.g. No-Such-Entry can
1595 * occur on a keepalive if the server has timed out our
1596 * connection. If we get one of these messages, we replace-all
1597 * right away to get back in synch faster.
1599 switch (rsp_status_code
) {
1600 case ISNS_RSP_INVALID_REGIS
:
1601 case ISNS_RSP_SRC_UNAUTHORIZED
:
1603 case ISNS_RSP_INVALID_UPDATE
:
1604 case ISNS_RSP_NO_SUCH_ENTRY
:
1618 isnst_register(iscsit_isns_svr_t
*svr
, isns_target_t
*itarget
,
1619 isns_reg_type_t regtype
)
1623 isns_pdu_t
*pdu
, *rsp
;
1624 size_t pdu_size
, rsp_size
;
1626 /* create TCP connection to the isns server */
1627 so
= isnst_open_so(&svr
->svr_sa
);
1632 pdu_size
= isnst_make_reg_pdu(&pdu
, itarget
, svr
, regtype
);
1633 if (pdu_size
== 0) {
1638 rc
= isnst_send_pdu(so
, pdu
);
1640 kmem_free(pdu
, pdu_size
);
1645 rsp_size
= isnst_rcv_pdu(so
, &rsp
);
1646 if (rsp_size
== 0) {
1647 kmem_free(pdu
, pdu_size
);
1652 rc
= isnst_verify_rsp(svr
, pdu
, rsp
, rsp_size
);
1654 kmem_free(pdu
, pdu_size
);
1655 kmem_free(rsp
, rsp_size
);
1662 * isnst_make_reg_pdu:
1664 * initial registration of all targets (replace-all)
1665 * initial registration of a single target (update-existing)
1666 * modify an existing target (update-existing)
1669 isnst_make_reg_pdu(isns_pdu_t
**pdu
, isns_target_t
*itarget
,
1670 iscsit_isns_svr_t
*svr
, isns_reg_type_t regtype
)
1676 boolean_t reg_all
= B_FALSE
;
1680 ASSERT(svr
->svr_monitor_hold
);
1682 * svr could have an empty target list if svr was added
1683 * by isnst_config_merge sometime after the last call to
1684 * copy_global_status_changes. Just skip this chance
1685 * to reregister. The next call to copy_global_status_changes
1686 * will sort things out.
1688 if (avl_numnodes(&svr
->svr_target_list
) == 0) {
1689 /* If no targets, nothing to register */
1690 ISNS_GLOBAL_UNLOCK();
1694 * Find a source attribute for this registration.
1696 * If updating a specific target for the first time, use that
1698 * If already registered, use a registered target
1699 * Otherwise, use the first target we are going to register.
1701 if (itarget
!= NULL
&& ! svr
->svr_registered
) {
1703 } else if (svr
->svr_registered
) {
1704 src
= isnst_get_registered_source_locked(svr
);
1707 * When registering to a server, and we don't know which
1708 * of our targets the server might already know,
1709 * cycle through each of our targets as source. The server
1710 * does source validation. If the server knows any of our
1711 * targets, it will eventually accept one of our registrations.
1714 isns_target_t
*jtarget
;
1716 if (svr
->svr_last_target_index
>=
1717 avl_numnodes(&svr
->svr_target_list
) - 1) {
1718 svr
->svr_last_target_index
= 0;
1720 svr
->svr_last_target_index
++;
1722 for (i
= 0, jtarget
= avl_first(&svr
->svr_target_list
);
1723 i
< svr
->svr_last_target_index
;
1724 i
++, jtarget
= AVL_NEXT(&svr
->svr_target_list
, jtarget
)) {
1725 ASSERT(jtarget
!= NULL
);
1728 ASSERT(src
!= NULL
);
1732 * Null target means we're replacing everything.
1734 if (itarget
== NULL
) {
1736 flags
= ISNS_FLAG_REPLACE_REG
;
1737 /* Reset itarget to the beginning of our list */
1738 itarget
= (isns_target_t
*)avl_first(&svr
->svr_target_list
);
1739 } else if (regtype
== ISNS_REGISTER_TARGET
) {
1740 flags
= ISNS_FLAG_REPLACE_REG
;
1741 ASSERT(!itarget
->target_delete_needed
);
1744 pdu_size
= isnst_create_pdu_header(ISNS_DEV_ATTR_REG
, pdu
, flags
);
1745 if (pdu_size
== 0) {
1746 ISNS_GLOBAL_UNLOCK();
1750 /* Source Attribute */
1752 len
= strlen(src
->target_info
->ti_tgt_name
) + 1;
1753 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_ISCSI_NAME_ATTR_ID
,
1754 len
, src
->target_info
->ti_tgt_name
, 0) != 0) {
1759 * Message Key Attributes - EID
1761 len
= strlen(isns_eid
) + 1;
1763 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_EID_ATTR_ID
,
1764 len
, isns_eid
, 0) != 0) {
1769 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_DELIMITER_ATTR_ID
,
1775 * Operating Attributes
1777 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_EID_ATTR_ID
, len
,
1778 isns_eid
, 0) != 0) {
1783 /* ENTITY Protocol - Section 6.2.2 */
1784 if (isnst_add_attr(*pdu
, pdu_size
,
1785 ISNS_ENTITY_PROTOCOL_ATTR_ID
,
1786 4, 0, ISNS_ENTITY_PROTOCOL_ISCSI
) != 0) {
1791 /* Registration Period -- use if not using ESI */
1792 if (!isns_use_esi
&&
1793 isnst_add_attr(*pdu
, pdu_size
,
1794 ISNS_ENTITY_REG_PERIOD_ATTR_ID
, 4,
1795 0, isns_registration_period
) != 0) {
1799 * Network entity portal information - only when
1800 * replacing all. Since targets are only registered
1801 * to iSNS when their portals are already registered
1802 * to iSNS, we can assume entity portals exist.
1804 if (isnst_reg_pdu_add_entity_portals(*pdu
, pdu_size
) != 0) {
1809 * Skip over delete-pending tgts. There must be at
1810 * least one non-deleted tgt, or it is an error.
1812 while (itarget
->target_delete_needed
) {
1813 itarget
= AVL_NEXT(&svr
->svr_target_list
,
1815 ASSERT(itarget
!= NULL
);
1820 /* Add information about each target or one target */
1823 /* iSCSI Name - Section 6.4.1 */
1824 str
= itarget
->target_info
->ti_tgt_name
;
1825 len
= strlen(str
) + 1;
1826 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_ISCSI_NAME_ATTR_ID
,
1827 len
, str
, 0) != 0) {
1831 /* iSCSI Node Type */
1832 if (isnst_add_attr(*pdu
, pdu_size
,
1833 ISNS_ISCSI_NODE_TYPE_ATTR_ID
, 4, 0,
1834 ISNS_TARGET_NODE_TYPE
) != 0) {
1839 str
= itarget
->target_info
->ti_tgt_alias
;
1841 sizeof (itarget
->target_info
->ti_tgt_alias
));
1843 /* Found alias in property list */
1844 if (isnst_add_attr(*pdu
, pdu_size
,
1845 ISNS_ISCSI_ALIAS_ATTR_ID
, len
+1, str
, 0) != 0) {
1850 if (isnst_reg_pdu_add_pg(*pdu
, pdu_size
, itarget
) != 0) {
1854 /* If registering one target, then we are done. */
1859 /* Skip over delete-pending tgts */
1861 itarget
= AVL_NEXT(&svr
->svr_target_list
, itarget
);
1862 } while (itarget
!= NULL
&& itarget
->target_delete_needed
);
1864 } while (itarget
!= NULL
);
1866 ISNS_GLOBAL_UNLOCK();
1870 /* packet too large, no memory (or other error) */
1871 len
= ntohs((*pdu
)->payload_len
);
1872 if (len
+ 1000 > isns_message_buf_size
) {
1873 /* Increase the PDU size we will ask for next time */
1874 if (isns_message_buf_size
* 2 <= ISNST_MAX_MSG_SIZE
) {
1875 isns_message_buf_size
*= 2;
1877 "Increasing isns_message_buf_size to %d",
1878 isns_message_buf_size
);
1880 cmn_err(CE_WARN
, "iscsit: isns: no space"
1881 " to send required PDU");
1885 kmem_free(*pdu
, pdu_size
);
1888 ISNS_GLOBAL_UNLOCK();
1893 isnst_reg_pdu_add_entity_portals(isns_pdu_t
*pdu
, size_t pdu_size
)
1896 isns_portal_t
*iportal
;
1898 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1900 iportal
= (isns_portal_t
*)avl_first(&isns_all_portals
);
1901 while (iportal
!= NULL
) {
1902 /* Do not include ESI port if not using ESI */
1903 if (isnst_add_portal_attr(pdu
, pdu_size
,
1904 ISNS_PORTAL_IP_ADDR_ATTR_ID
,
1905 ISNS_PORTAL_PORT_ATTR_ID
,
1906 &iportal
->portal_addr
,
1907 isns_use_esi
/* ESI info */) != 0) {
1911 iportal
= AVL_NEXT(&isns_all_portals
, iportal
);
1919 * isnst_reg_pdu_add_pg -- add the PG and PGT entries for one target.
1922 isnst_reg_pdu_add_pg(isns_pdu_t
*pdu
, size_t pdu_size
, isns_target_t
*itarget
)
1925 avl_tree_t null_portals
;
1926 isns_target_info_t
*ti
;
1929 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1931 ti
= itarget
->target_info
;
1934 * If all registered targets only use the default TPGT, then
1935 * we can skip sending PG info to the iSNS server.
1937 if (num_tpg_portals
== 0)
1941 * For each target, we start with the full portal list,
1942 * and then remove portals as we add them to TPGTs for this target.
1943 * At the end, all the remaining portals go into the "null pg".
1944 * We use the "null_portals" list to track this.
1946 avl_create(&null_portals
, isnst_portal_avl_compare
,
1947 sizeof (isns_portal_t
), offsetof(isns_portal_t
, portal_node
));
1948 isnst_copy_portal_list(&isns_all_portals
, &null_portals
);
1950 for (tig
= list_head(&ti
->ti_tpgt_list
);
1952 tig
= list_next(&ti
->ti_tpgt_list
, tig
)) {
1954 if (tig
->ti_tpgt_tag
== ISCSIT_DEFAULT_TPGT
) {
1955 /* Add portal info from list of default portals */
1956 if (isnst_add_default_pg(pdu
, pdu_size
,
1957 &null_portals
) != 0) {
1962 /* Add portal info from this TPGT's entries */
1963 if (isnst_add_tpg_pg(pdu
, pdu_size
, tig
,
1964 &null_portals
) != 0) {
1971 /* Add the remaining portals (if any) to the null PG */
1973 isnst_add_null_pg(pdu
, pdu_size
, &null_portals
) != 0) {
1976 isnst_clear_portal_list(&null_portals
);
1977 avl_destroy(&null_portals
);
1981 /* Write one TPGT's info into the PDU */
1983 isnst_add_tpg_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
1984 isns_tpgt_t
*tig
, avl_tree_t
*null_portal_list
)
1986 isns_tpgt_addr_t
*tip
;
1989 ASSERT(ISNS_GLOBAL_LOCK_HELD());
1990 ASSERT(tig
->ti_tpgt_tag
!= ISCSIT_DEFAULT_TPGT
);
1992 /* Portal Group Tag */
1993 if (isnst_add_attr(pdu
, pdu_size
,
1994 ISNS_PG_TAG_ATTR_ID
, 4, 0, tig
->ti_tpgt_tag
) != 0) {
1999 tip
= list_head(&tig
->ti_portal_list
);
2000 ASSERT(tip
!= NULL
);
2002 /* PG Portal Addr and PG Portal Port */
2003 if (isnst_add_portal_attr(pdu
, pdu_size
,
2004 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID
,
2005 ISNS_PG_PORTAL_PORT_ATTR_ID
,
2006 &tip
->portal_addr
, B_FALSE
/* ESI */) != 0) {
2010 isnst_remove_from_portal_list(&tip
->portal_addr
,
2013 tip
= list_next(&tig
->ti_portal_list
, tip
);
2014 } while (tip
!= NULL
);
2021 isnst_add_default_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
2022 avl_tree_t
*null_portal_list
)
2024 isns_portal_t
*iportal
;
2026 ASSERT(ISNS_GLOBAL_LOCK_HELD());
2028 if (num_default_portals
== 0) {
2030 * It is OK for a target with default-portals to be
2031 * online from an STMF perspective and yet all
2032 * default portals are down. if other (non-default)
2033 * portals do exist, we will still announce the target
2034 * to the isns server. In this case, we will specify
2035 * all the active non-default portals as NULL portals.
2036 * This is an OK state.
2038 * There is a corner case if non-default portals have
2039 * been marked online but the targets that use them
2040 * are not fully online yet, AND all the default portals
2041 * are down. In this case, the iSNS server will receive
2042 * a DevAttrReg pdu that announces both non-default
2043 * portals and default-portal-only targets. In other
2044 * words, there may be no target that has an active
2045 * portal. The iSNS spec does not forbid this case.
2047 * Both of the above cases are somewhat theoretical.
2048 * If the default portals are down we probably cannot
2049 * get any messages through to the iSNS server anyway.
2054 /* Portal Group Tag */
2055 if (isnst_add_attr(pdu
, pdu_size
,
2056 ISNS_PG_TAG_ATTR_ID
, 4, 0, ISCSIT_DEFAULT_TPGT
) != 0) {
2060 for (iportal
= avl_first(&isns_all_portals
);
2062 iportal
= AVL_NEXT(&isns_all_portals
, iportal
)) {
2063 if (iportal
->portal_default
) {
2064 /* PG Portal Addr and PG Portal Port */
2065 if (isnst_add_portal_attr(pdu
, pdu_size
,
2066 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID
,
2067 ISNS_PG_PORTAL_PORT_ATTR_ID
,
2068 &iportal
->portal_addr
, B_FALSE
) != 0) {
2071 isnst_remove_from_portal_list(&iportal
->portal_addr
,
2080 isnst_add_null_pg(isns_pdu_t
*pdu
, size_t pdu_size
,
2081 avl_tree_t
*null_portal_list
)
2083 isns_portal_t
*iportal
;
2085 /* If all portals accounted for, no NULL PG needed */
2086 if (avl_numnodes(null_portal_list
) == 0) {
2090 /* NULL Portal Group Tag means no access via these portals. */
2091 if (isnst_add_attr(pdu
, pdu_size
,
2092 ISNS_PG_TAG_ATTR_ID
, 0, 0, 0) != 0) {
2096 for (iportal
= avl_first(null_portal_list
);
2098 iportal
= AVL_NEXT(null_portal_list
, iportal
)) {
2099 if (isnst_add_portal_attr(pdu
, pdu_size
,
2100 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID
,
2101 ISNS_PG_PORTAL_PORT_ATTR_ID
,
2102 &iportal
->portal_addr
, B_FALSE
) != 0) {
2111 isnst_add_portal_attr(isns_pdu_t
*pdu
, size_t pdu_size
,
2112 uint32_t ip_attr_id
, uint32_t port_attr_id
,
2113 struct sockaddr_storage
*ss
, boolean_t esi_info
)
2115 struct sockaddr_in
*in
;
2116 struct sockaddr_in6
*in6
;
2117 uint32_t attr_numeric_data
;
2120 in
= (struct sockaddr_in
*)ss
;
2121 in6
= (struct sockaddr_in6
*)ss
;
2123 ASSERT((ss
->ss_family
== AF_INET
) || (ss
->ss_family
== AF_INET6
));
2125 if (ss
->ss_family
== AF_INET
) {
2126 attr_numeric_data
= sizeof (in_addr_t
);
2127 inaddrp
= (void *)&in
->sin_addr
;
2128 } else if (ss
->ss_family
== AF_INET6
) {
2129 attr_numeric_data
= sizeof (in6_addr_t
);
2130 inaddrp
= (void *)&in6
->sin6_addr
;
2133 /* Portal Group Portal IP Address */
2134 if (isnst_add_attr(pdu
, pdu_size
, ip_attr_id
,
2135 16, inaddrp
, attr_numeric_data
) != 0) {
2139 /* Portal Group Portal Port */
2140 if (isnst_add_attr(pdu
, pdu_size
, port_attr_id
,
2141 4, 0, ntohs(in
->sin_port
)) != 0) {
2145 mutex_enter(&esi
.esi_mutex
);
2146 if (esi_info
&& esi
.esi_valid
) {
2147 /* ESI interval and port */
2148 if (isnst_add_attr(pdu
, pdu_size
, ISNS_ESI_INTERVAL_ATTR_ID
, 4,
2149 NULL
, isns_default_esi_interval
) != 0) {
2153 if (isnst_add_attr(pdu
, pdu_size
, ISNS_ESI_PORT_ATTR_ID
, 4,
2154 NULL
, esi
.esi_port
) != 0) {
2158 mutex_exit(&esi
.esi_mutex
);
2164 isnst_deregister(iscsit_isns_svr_t
*svr
, isns_target_t
*itarget
)
2167 isns_pdu_t
*pdu
, *rsp
;
2168 size_t pdu_size
, rsp_size
;
2171 so
= isnst_open_so(&svr
->svr_sa
);
2177 pdu_size
= isnst_make_dereg_pdu(svr
, &pdu
, itarget
);
2178 if (pdu_size
== 0) {
2183 rc
= isnst_send_pdu(so
, pdu
);
2186 kmem_free(pdu
, pdu_size
);
2190 rsp_size
= isnst_rcv_pdu(so
, &rsp
);
2191 if (rsp_size
== 0) {
2193 kmem_free(pdu
, pdu_size
);
2197 rc
= isnst_verify_rsp(svr
, pdu
, rsp
, rsp_size
);
2200 kmem_free(pdu
, pdu_size
);
2201 kmem_free(rsp
, rsp_size
);
2207 isnst_keepalive(iscsit_isns_svr_t
*svr
)
2210 isns_pdu_t
*pdu
, *rsp
;
2211 size_t pdu_size
, rsp_size
;
2214 so
= isnst_open_so(&svr
->svr_sa
);
2220 pdu_size
= isnst_make_keepalive_pdu(svr
, &pdu
);
2221 if (pdu_size
== 0) {
2226 rc
= isnst_send_pdu(so
, pdu
);
2229 kmem_free(pdu
, pdu_size
);
2233 rsp_size
= isnst_rcv_pdu(so
, &rsp
);
2234 if (rsp_size
== 0) {
2236 kmem_free(pdu
, pdu_size
);
2240 rc
= isnst_verify_rsp(svr
, pdu
, rsp
, rsp_size
);
2243 kmem_free(pdu
, pdu_size
);
2244 kmem_free(rsp
, rsp_size
);
2250 isnst_make_dereg_pdu(iscsit_isns_svr_t
*svr
, isns_pdu_t
**pdu
,
2251 isns_target_t
*itarget
)
2258 * create DevDereg Message with all of target nodes
2260 pdu_size
= isnst_create_pdu_header(ISNS_DEV_DEREG
, pdu
, 0);
2261 if (pdu_size
== 0) {
2266 * Source attribute - Must be a storage node in the same
2269 if (svr
->svr_registered
) {
2270 src
= isnst_get_registered_source(svr
);
2271 } else if (itarget
!= NULL
) {
2274 goto dereg_pdu_error
;
2277 len
= strlen(src
->target_info
->ti_tgt_name
) + 1;
2278 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_ISCSI_NAME_ATTR_ID
,
2279 len
, src
->target_info
->ti_tgt_name
, 0) != 0) {
2280 goto dereg_pdu_error
;
2285 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_DELIMITER_ATTR_ID
,
2287 goto dereg_pdu_error
;
2291 * Operating attributes
2293 if (itarget
== NULL
) {
2294 /* dereg everything */
2295 len
= strlen(isns_eid
) + 1;
2296 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_EID_ATTR_ID
,
2297 len
, isns_eid
, 0) != 0) {
2298 goto dereg_pdu_error
;
2301 /* dereg one target only */
2302 len
= strlen(itarget
->target_info
->ti_tgt_name
) + 1;
2303 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_ISCSI_NAME_ATTR_ID
,
2304 len
, itarget
->target_info
->ti_tgt_name
, 0) != 0) {
2305 goto dereg_pdu_error
;
2312 kmem_free(*pdu
, pdu_size
);
2319 isnst_make_keepalive_pdu(iscsit_isns_svr_t
*svr
, isns_pdu_t
**pdu
)
2325 ASSERT(svr
->svr_registered
);
2328 * create DevAttrQuery Message
2330 pdu_size
= isnst_create_pdu_header(ISNS_DEV_ATTR_QRY
, pdu
, 0);
2331 if (pdu_size
== 0) {
2336 * Source attribute - Must be a iscsi target in the same
2339 src
= isnst_get_registered_source(svr
);
2341 len
= strlen(src
->target_info
->ti_tgt_name
) + 1;
2342 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_ISCSI_NAME_ATTR_ID
,
2343 len
, src
->target_info
->ti_tgt_name
, 0) != 0) {
2344 goto keepalive_pdu_error
;
2348 len
= strlen(isns_eid
) + 1;
2349 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_EID_ATTR_ID
,
2350 len
, isns_eid
, 0) != 0) {
2351 goto keepalive_pdu_error
;
2354 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_DELIMITER_ATTR_ID
,
2356 goto keepalive_pdu_error
;
2359 /* Values to Fetch -- EID */
2360 if (isnst_add_attr(*pdu
, pdu_size
, ISNS_EID_ATTR_ID
,
2362 goto keepalive_pdu_error
;
2368 keepalive_pdu_error
:
2369 kmem_free(*pdu
, pdu_size
);
2375 static isns_target_t
*
2376 isnst_get_registered_source(iscsit_isns_svr_t
*svr
)
2378 isns_target_t
*itarget
;
2381 * If svr is registered, then there must be at least one
2382 * target that is registered to that svr.
2385 ASSERT(svr
->svr_monitor_hold
);
2386 itarget
= isnst_get_registered_source_locked(svr
);
2387 ISNS_GLOBAL_UNLOCK();
2391 static isns_target_t
*
2392 isnst_get_registered_source_locked(iscsit_isns_svr_t
*svr
)
2394 isns_target_t
*itarget
;
2396 ASSERT(ISNS_GLOBAL_LOCK_HELD());
2397 ASSERT(svr
->svr_registered
);
2398 ASSERT((avl_numnodes(&svr
->svr_target_list
) != 0));
2400 itarget
= avl_first(&svr
->svr_target_list
);
2402 if (itarget
->target_registered
== B_TRUE
)
2404 itarget
= AVL_NEXT(&svr
->svr_target_list
, itarget
);
2405 } while (itarget
!= NULL
);
2406 ASSERT(itarget
!= NULL
);
2411 isnst_verify_rsp(iscsit_isns_svr_t
*svr
, isns_pdu_t
*pdu
,
2412 isns_pdu_t
*rsp
, size_t rsp_size
)
2415 int payload_len
, rsp_payload_len
;
2420 uint32_t attr_len
, attr_id
, esi_interval
;
2423 * Ensure we have at least a valid header (don't count the
2426 if (rsp_size
< offsetof(isns_pdu_t
, payload
)) {
2427 ISNST_LOG(CE_WARN
, "Invalid iSNS PDU header, %d of %d bytes",
2428 (int)rsp_size
, (int)offsetof(isns_pdu_t
, payload
));
2432 /* Make sure we have the amount of data that the header specifies */
2433 payload_len
= ntohs(rsp
->payload_len
);
2434 if (rsp_size
< (payload_len
+ offsetof(isns_pdu_t
, payload
))) {
2435 ISNST_LOG(CE_WARN
, "Invalid iSNS response, %d of %d bytes",
2437 (int)(payload_len
+ offsetof(isns_pdu_t
, payload
)));
2441 /* Find the start of all operational parameters */
2442 rsp_payload_len
= isnst_pdu_get_op(rsp
, &pp
);
2444 * Make sure isnst_pdu_get_op didn't encounter an error
2445 * in the attributes.
2451 /* verify response transaction id */
2452 if (ntohs(rsp
->xid
) != ntohs(pdu
->xid
)) {
2456 /* check the error code */
2457 resp
= (isns_resp_t
*)((void *)&rsp
->payload
[0]);
2459 status
= ntohl(resp
->status
);
2461 /* validate response function id */
2462 func_id
= ntohs(rsp
->func_id
);
2463 switch (ntohs(pdu
->func_id
)) {
2464 case ISNS_DEV_ATTR_REG
:
2465 if (func_id
!= ISNS_DEV_ATTR_REG_RSP
) {
2469 /* Only look through response if msg status says OK */
2474 * Get the ESI interval returned by the server. It could
2475 * be different than what we asked for. We never know which
2476 * portal a request may come in on, and any server could demand
2477 * any interval. We'll simply keep track of the largest
2478 * interval for use in monitoring.
2481 attr
= (isns_tlv_t
*)((void *)pp
);
2482 while (rsp_payload_len
>= 8) {
2483 attr_len
= ntohl(attr
->attr_len
);
2484 attr_id
= ntohl(attr
->attr_id
);
2485 if (attr_id
== ISNS_ESI_INTERVAL_ATTR_ID
) {
2486 if (attr_len
!= 4 ||
2487 attr_len
> rsp_payload_len
- 8) {
2488 /* Mal-formed packet */
2492 ntohl(*((uint32_t *)
2493 ((void *)(&attr
->attr_value
))));
2496 ASSERT(svr
->svr_monitor_hold
);
2497 if (esi_interval
> svr
->svr_esi_interval
)
2498 svr
->svr_esi_interval
= esi_interval
;
2499 ISNS_GLOBAL_UNLOCK();
2503 rsp_payload_len
-= (8 + attr_len
);
2504 attr
= (isns_tlv_t
*)
2505 ((void *)((uint8_t *)attr
+ attr_len
+ 8));
2509 case ISNS_DEV_DEREG
:
2510 if (func_id
!= ISNS_DEV_DEREG_RSP
) {
2514 case ISNS_DEV_ATTR_QRY
:
2515 /* Keepalive Response */
2516 if (func_id
!= ISNS_DEV_ATTR_QRY_RSP
) {
2521 boolean_t found_eid
= B_FALSE
;
2523 /* Scan the operational parameters */
2524 attr
= (isns_tlv_t
*)((void *)pp
);
2525 while (rsp_payload_len
>= 8) {
2526 attr_len
= ntohl(attr
->attr_len
);
2527 attr_id
= ntohl(attr
->attr_id
);
2528 if (attr_id
== ISNS_EID_ATTR_ID
&&
2530 attr_len
<= rsp_payload_len
- 8) {
2532 * If the isns server knows us, the
2533 * response will include our EID in
2534 * the operational parameters, i.e.
2535 * after the delimiter.
2536 * Just receiving this pattern
2537 * is good enough to tell the isns
2538 * server still knows us.
2544 rsp_payload_len
-= (8 + attr_len
);
2545 attr
= (isns_tlv_t
*)
2546 ((void *)((uint8_t *)attr
+ attr_len
+ 8));
2549 status
= ISNS_RSP_NO_SUCH_ENTRY
;
2552 if (status
== ISNS_RSP_NO_SUCH_ENTRY
) {
2553 char server_buf
[IDM_SA_NTOP_BUFSIZ
];
2555 * The iSNS server has forgotten about us.
2556 * We will re-register everything.
2557 * This can happen e.g. if ESI probes time out,
2558 * or if the iSNS server does a factory reset.
2560 ISNST_LOG(CE_WARN
, "iscsit: iSNS server %s"
2561 " forgot about us and has to be reminded.",
2562 idm_sa_ntop(&svr
->svr_sa
,
2563 server_buf
, sizeof (server_buf
)));
2564 /* isnst_retry_registration will trigger the reset */
2574 /* Update the last time we heard from this server */
2577 ASSERT(svr
->svr_monitor_hold
);
2578 svr
->svr_last_msg
= ddi_get_lbolt();
2579 ISNS_GLOBAL_UNLOCK();
2588 isnst_pdu_get_op(isns_pdu_t
*pdu
, uint8_t **pp
)
2591 uint16_t payload_len
;
2598 payload_len
= ntohs(pdu
->payload_len
);
2599 resp
= (isns_resp_t
*)((void *)&pdu
->payload
[0]);
2601 /* find the operating attributes */
2602 if (payload_len
< sizeof (resp
->status
)) {
2603 ISNST_LOG(CE_WARN
, "Invalid iSNS response, %d payload bytes",
2609 payload_len
-= sizeof (resp
->status
);
2610 payload
= &resp
->data
[0];
2612 while (payload_len
>= (sizeof (isns_tlv_t
) - 1)) {
2613 attr
= (isns_tlv_t
*)((void *)payload
);
2614 tlv_len
= offsetof(isns_tlv_t
, attr_value
) +
2615 ntohl(attr
->attr_len
);
2616 if (payload_len
>= tlv_len
) {
2618 payload_len
-= tlv_len
;
2619 attr_id
= ntohl(attr
->attr_id
);
2620 if (attr_id
== ISNS_DELIMITER_ATTR_ID
) {
2624 /* mal-formed packet */
2632 return (payload_len
);
2636 isnst_create_pdu_header(uint16_t func_id
, isns_pdu_t
**pdu
, uint16_t flags
)
2638 size_t pdu_size
= isns_message_buf_size
;
2640 *pdu
= (isns_pdu_t
*)kmem_zalloc(pdu_size
, KM_NOSLEEP
);
2642 (*pdu
)->version
= htons((uint16_t)ISNSP_VERSION
);
2643 (*pdu
)->func_id
= htons((uint16_t)func_id
);
2644 (*pdu
)->payload_len
= htons(0);
2645 (*pdu
)->flags
= htons(flags
);
2647 (*pdu
)->xid
= htons(GET_XID());
2648 (*pdu
)->seq
= htons(0);
2657 isnst_add_attr(isns_pdu_t
*pdu
,
2658 size_t max_pdu_size
,
2662 uint32_t attr_numeric_data
)
2664 isns_tlv_t
*attr_tlv
;
2665 uint8_t *payload_ptr
;
2666 uint16_t payload_len
;
2667 uint32_t normalized_attr_len
;
2668 uint64_t attr_tlv_len
;
2670 /* The attribute length must be 4-byte aligned. Section 5.1.3. */
2671 normalized_attr_len
= (attr_len
% 4) == 0 ?
2672 (attr_len
) : (attr_len
+ (4 - (attr_len
% 4)));
2673 attr_tlv_len
= ISNS_TLV_ATTR_ID_LEN
+
2674 ISNS_TLV_ATTR_LEN_LEN
+ normalized_attr_len
;
2676 /* Check if we are going to exceed the maximum PDU length. */
2677 payload_len
= ntohs(pdu
->payload_len
);
2678 if ((payload_len
+ attr_tlv_len
) > max_pdu_size
) {
2682 attr_tlv
= (isns_tlv_t
*)kmem_zalloc(attr_tlv_len
, KM_SLEEP
);
2684 attr_tlv
->attr_id
= htonl(attr_id
);
2687 case ISNS_DELIMITER_ATTR_ID
:
2690 case ISNS_PORTAL_IP_ADDR_ATTR_ID
:
2691 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID
:
2692 if (attr_numeric_data
== sizeof (in_addr_t
)) {
2694 attr_tlv
->attr_value
[10] = 0xFF;
2695 attr_tlv
->attr_value
[11] = 0xFF;
2696 bcopy(attr_data
, ((attr_tlv
->attr_value
) + 12),
2697 sizeof (in_addr_t
));
2698 } else if (attr_numeric_data
== sizeof (in6_addr_t
)) {
2700 bcopy(attr_data
, attr_tlv
->attr_value
,
2701 sizeof (in6_addr_t
));
2702 } else if (attr_numeric_data
== 0) {
2706 kmem_free(attr_tlv
, attr_tlv_len
);
2712 case ISNS_EID_ATTR_ID
:
2713 case ISNS_ISCSI_NAME_ATTR_ID
:
2714 case ISNS_ISCSI_ALIAS_ATTR_ID
:
2715 case ISNS_PG_ISCSI_NAME_ATTR_ID
:
2716 if (attr_len
&& attr_data
) {
2717 bcopy((char *)attr_data
,
2718 attr_tlv
->attr_value
, attr_len
);
2723 if (attr_len
== 8) {
2724 *(uint64_t *)((void *)attr_tlv
->attr_value
) =
2725 BE_64((uint64_t)attr_numeric_data
);
2726 } else if (attr_len
== 4) {
2727 *(uint32_t *)((void *)attr_tlv
->attr_value
) =
2728 htonl((uint32_t)attr_numeric_data
);
2733 attr_tlv
->attr_len
= htonl(normalized_attr_len
);
2735 * Convert the network byte ordered payload length to host byte
2736 * ordered for local address calculation.
2738 payload_len
= ntohs(pdu
->payload_len
);
2739 payload_ptr
= pdu
->payload
+ payload_len
;
2740 bcopy(attr_tlv
, payload_ptr
, attr_tlv_len
);
2741 payload_len
+= attr_tlv_len
;
2744 * Convert the host byte ordered payload length back to network
2745 * byte ordered - it's now ready to be sent on the wire.
2747 pdu
->payload_len
= htons(payload_len
);
2749 kmem_free(attr_tlv
, attr_tlv_len
);
2756 isnst_so_timeout(void *so
)
2758 /* Wake up any sosend or sorecv blocked on this socket */
2763 isnst_send_pdu(void *so
, isns_pdu_t
*pdu
)
2765 size_t total_len
, payload_len
, send_len
;
2767 uint16_t flags
, seq
;
2768 timeout_id_t send_timer
;
2772 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2774 /* update pdu flags */
2775 flags
= ntohs(pdu
->flags
);
2776 flags
|= ISNS_FLAG_CLIENT
;
2777 flags
|= ISNS_FLAG_FIRST_PDU
;
2779 /* initalize sequence number */
2782 payload
= pdu
->payload
;
2784 /* total payload length */
2785 total_len
= ntohs(pdu
->payload_len
);
2787 /* fill in the pdu header */
2788 iov
[0].iov_base
= (void *)pdu
;
2789 iov
[0].iov_len
= ISNSP_HEADER_SIZE
;
2792 /* split the payload accordingly */
2793 if (total_len
> ISNSP_MAX_PAYLOAD_SIZE
) {
2794 payload_len
= ISNSP_MAX_PAYLOAD_SIZE
;
2796 payload_len
= total_len
;
2797 /* set the last pdu flag */
2798 flags
|= ISNS_FLAG_LAST_PDU
;
2801 /* set back the pdu flags */
2802 pdu
->flags
= htons(flags
);
2803 /* set the sequence number */
2804 pdu
->seq
= htons(seq
);
2805 /* set the payload length */
2806 pdu
->payload_len
= htons(payload_len
);
2808 /* fill in the payload */
2809 iov
[1].iov_base
= (void *)payload
;
2810 iov
[1].iov_len
= payload_len
;
2812 DTRACE_PROBE3(isnst__pdu__send
, uint16_t, ntohs(pdu
->func_id
),
2813 uint16_t, ntohs(pdu
->payload_len
), caddr_t
, pdu
);
2816 send_len
= ISNSP_HEADER_SIZE
+ payload_len
;
2817 send_timer
= timeout(isnst_so_timeout
, so
,
2818 drv_usectohz(isns_timeout_usec
));
2819 rc
= idm_iov_sosend(so
, &iov
[0], 2, send_len
);
2820 (void) untimeout(send_timer
);
2822 flags
&= ~ISNS_FLAG_FIRST_PDU
;
2823 payload
+= payload_len
;
2824 total_len
-= payload_len
;
2826 /* increase the sequence number */
2829 } while (rc
== 0 && total_len
> 0);
2835 isnst_rcv_pdu(void *so
, isns_pdu_t
**pdu
)
2837 size_t total_pdu_len
;
2838 size_t total_payload_len
;
2840 size_t combined_len
;
2841 isns_pdu_t tmp_pdu_hdr
;
2842 isns_pdu_t
*combined_pdu
;
2844 uint8_t *combined_payload
;
2845 timeout_id_t rcv_timer
;
2849 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2852 total_pdu_len
= total_payload_len
= 0;
2857 /* receive the pdu header */
2858 rcv_timer
= timeout(isnst_so_timeout
, so
,
2859 drv_usectohz(isns_timeout_usec
));
2860 if (idm_sorecv(so
, &tmp_pdu_hdr
, ISNSP_HEADER_SIZE
) != 0 ||
2861 ntohs(tmp_pdu_hdr
.seq
) != seq
) {
2862 (void) untimeout(rcv_timer
);
2865 (void) untimeout(rcv_timer
);
2867 /* receive the payload */
2868 payload_len
= ntohs(tmp_pdu_hdr
.payload_len
);
2869 if (payload_len
> ISNST_MAX_MSG_SIZE
) {
2872 payload
= kmem_alloc(payload_len
, KM_NOSLEEP
);
2873 if (payload
== NULL
) {
2876 rcv_timer
= timeout(isnst_so_timeout
, so
,
2877 drv_usectohz(ISNS_RCV_TIMER_SECONDS
* 1000000));
2878 if (idm_sorecv(so
, payload
, payload_len
) != 0) {
2879 (void) untimeout(rcv_timer
);
2882 (void) untimeout(rcv_timer
);
2884 /* combine the pdu if it is not the first one */
2885 if (total_pdu_len
> 0) {
2886 combined_len
= total_pdu_len
+ payload_len
;
2887 combined_pdu
= kmem_alloc(combined_len
, KM_SLEEP
);
2888 if (combined_pdu
== NULL
) {
2891 bcopy(*pdu
, combined_pdu
, total_pdu_len
);
2893 &combined_pdu
->payload
[total_payload_len
];
2894 bcopy(payload
, combined_payload
, payload_len
);
2895 kmem_free(*pdu
, total_pdu_len
);
2896 kmem_free(payload
, payload_len
);
2897 *pdu
= combined_pdu
;
2898 total_payload_len
+= payload_len
;
2899 total_pdu_len
+= payload_len
;
2900 (*pdu
)->payload_len
= htons(total_payload_len
);
2902 total_payload_len
= payload_len
;
2903 total_pdu_len
= ISNSP_HEADER_SIZE
+ payload_len
;
2904 *pdu
= kmem_alloc(total_pdu_len
, KM_NOSLEEP
);
2908 bcopy(&tmp_pdu_hdr
, *pdu
, ISNSP_HEADER_SIZE
);
2909 bcopy(payload
, &(*pdu
)->payload
[0], payload_len
);
2910 kmem_free(payload
, payload_len
);
2914 /* the flags of pdu which is just received */
2915 flags
= ntohs(tmp_pdu_hdr
.flags
);
2917 /* increase sequence number by one */
2919 } while ((flags
& ISNS_FLAG_LAST_PDU
) == 0);
2921 DTRACE_PROBE3(isnst__pdu__recv
, uint16_t, ntohs((*pdu
)->func_id
),
2922 size_t, total_payload_len
, caddr_t
, *pdu
);
2924 return (total_pdu_len
);
2928 kmem_free(*pdu
, total_pdu_len
);
2931 if (payload
!= NULL
) {
2932 kmem_free(payload
, payload_len
);
2938 isnst_open_so(struct sockaddr_storage
*sa
)
2943 ASSERT(! ISNS_GLOBAL_LOCK_HELD());
2945 /* determine local IP address */
2946 if (sa
->ss_family
== AF_INET
) {
2948 sa_sz
= sizeof (struct sockaddr_in
);
2951 so
= idm_socreate(AF_INET
, SOCK_STREAM
, 0);
2954 sa_sz
= sizeof (struct sockaddr_in6
);
2957 so
= idm_socreate(AF_INET6
, SOCK_STREAM
, 0);
2961 if (idm_so_timed_socket_connect(so
, sa
, sa_sz
,
2962 isns_timeout_usec
) != 0) {
2963 /* not calling isnst_close_so() to */
2964 /* make dtrace output look clear */
2972 char server_buf
[IDM_SA_NTOP_BUFSIZ
];
2973 ISNST_LOG(CE_WARN
, "open iSNS Server %s failed",
2974 idm_sa_ntop(sa
, server_buf
,
2975 sizeof (server_buf
)));
2976 DTRACE_PROBE1(isnst__connect__fail
,
2977 struct sockaddr_storage
*, sa
);
2984 isnst_close_so(void *so
)
2995 isnst_esi_start(void)
2997 if (isns_use_esi
== B_FALSE
) {
2998 ISNST_LOG(CE_NOTE
, "ESI disabled by isns_use_esi=FALSE");
3002 ISNST_LOG(CE_NOTE
, "isnst_esi_start");
3004 mutex_enter(&esi
.esi_mutex
);
3005 ASSERT(esi
.esi_enabled
== B_FALSE
);
3006 ASSERT(esi
.esi_thread_running
== B_FALSE
);
3008 esi
.esi_enabled
= B_TRUE
;
3009 esi
.esi_valid
= B_FALSE
;
3010 esi
.esi_thread
= thread_create(NULL
, 0, isnst_esi_thread
,
3011 (void *)&esi
, 0, &p0
, TS_RUN
, minclsyspri
);
3014 * Wait for the thread to start
3016 while (!esi
.esi_thread_running
) {
3017 cv_wait(&esi
.esi_cv
, &esi
.esi_mutex
);
3019 mutex_exit(&esi
.esi_mutex
);
3025 boolean_t need_offline
= B_FALSE
;
3027 ISNST_LOG(CE_NOTE
, "isnst_esi_stop");
3029 /* Shutdown ESI listening socket, wait for thread to terminate */
3030 mutex_enter(&esi
.esi_mutex
);
3031 if (esi
.esi_enabled
) {
3032 esi
.esi_enabled
= B_FALSE
;
3033 if (esi
.esi_valid
) {
3034 need_offline
= B_TRUE
;
3036 mutex_exit(&esi
.esi_mutex
);
3038 idm_soshutdown(esi
.esi_so
);
3039 idm_sodestroy(esi
.esi_so
);
3041 thread_join(esi
.esi_thread_did
);
3043 mutex_exit(&esi
.esi_mutex
);
3050 * This function listens on a socket for incoming connections from an
3051 * iSNS server until told to stop.
3056 isnst_esi_thread(void *arg
)
3059 struct sockaddr_in6 sin6
;
3060 socklen_t sin_addrlen
;
3066 bzero(&sin6
, sizeof (struct sockaddr_in6
));
3067 sin_addrlen
= sizeof (struct sockaddr_in6
);
3069 esi
.esi_thread_did
= curthread
->t_did
;
3071 mutex_enter(&esi
.esi_mutex
);
3074 * Mark the thread as running and the portal as no longer new.
3076 esi
.esi_thread_running
= B_TRUE
;
3077 cv_signal(&esi
.esi_cv
);
3079 while (esi
.esi_enabled
) {
3081 * Create a socket to listen for requests from the iSNS server.
3083 if ((esi
.esi_so
= idm_socreate(PF_INET6
, SOCK_STREAM
, 0)) ==
3086 "isnst_esi_thread: Unable to create socket");
3087 mutex_exit(&esi
.esi_mutex
);
3089 mutex_enter(&esi
.esi_mutex
);
3094 * Set options, bind, and listen until we're told to stop
3096 bzero(&sin6
, sizeof (sin6
));
3097 sin6
.sin6_family
= AF_INET6
;
3098 sin6
.sin6_port
= htons(0);
3099 sin6
.sin6_addr
= in6addr_any
;
3101 (void) ksocket_setsockopt(esi
.esi_so
, SOL_SOCKET
,
3102 SO_REUSEADDR
, (char *)&on
, sizeof (on
), CRED());
3104 if (ksocket_bind(esi
.esi_so
, (struct sockaddr
*)&sin6
,
3105 sizeof (sin6
), CRED()) != 0) {
3106 ISNST_LOG(CE_WARN
, "Unable to bind socket for ESI");
3107 idm_sodestroy(esi
.esi_so
);
3108 mutex_exit(&esi
.esi_mutex
);
3110 mutex_enter(&esi
.esi_mutex
);
3115 * Get the port (sin6 is meaningless at this point)
3117 (void) ksocket_getsockname(esi
.esi_so
,
3118 (struct sockaddr
*)(&sin6
), &sin_addrlen
, CRED());
3120 ntohs(((struct sockaddr_in6
*)(&sin6
))->sin6_port
);
3122 if ((rc
= ksocket_listen(esi
.esi_so
, 5, CRED())) != 0) {
3123 ISNST_LOG(CE_WARN
, "isnst_esi_thread: listen "
3124 "failure 0x%x", rc
);
3125 idm_sodestroy(esi
.esi_so
);
3126 mutex_exit(&esi
.esi_mutex
);
3128 mutex_enter(&esi
.esi_mutex
);
3132 ksocket_hold(esi
.esi_so
);
3133 esi
.esi_valid
= B_TRUE
;
3134 while (esi
.esi_enabled
) {
3135 mutex_exit(&esi
.esi_mutex
);
3137 DTRACE_PROBE3(iscsit__isns__esi__accept__wait
,
3138 boolean_t
, esi
.esi_enabled
,
3139 ksocket_t
, esi
.esi_so
,
3140 struct sockaddr_in6
, &sin6
);
3141 if ((rc
= ksocket_accept(esi
.esi_so
, NULL
, NULL
,
3142 &newso
, CRED())) != 0) {
3143 mutex_enter(&esi
.esi_mutex
);
3144 DTRACE_PROBE2(iscsit__isns__esi__accept__fail
,
3145 int, rc
, boolean_t
, esi
.esi_enabled
);
3147 * If we were interrupted with EINTR
3148 * it's not really a failure.
3150 ISNST_LOG(CE_WARN
, "isnst_esi_thread: "
3151 "accept failure (0x%x)", rc
);
3159 DTRACE_PROBE2(iscsit__isns__esi__accept
,
3160 boolean_t
, esi
.esi_enabled
,
3163 pl_size
= isnst_rcv_pdu(newso
, &pdu
);
3165 ISNST_LOG(CE_WARN
, "isnst_esi_thread: "
3167 idm_soshutdown(newso
);
3168 idm_sodestroy(newso
);
3170 mutex_enter(&esi
.esi_mutex
);
3174 isnst_handle_esi_req(newso
, pdu
, pl_size
);
3176 idm_soshutdown(newso
);
3177 idm_sodestroy(newso
);
3179 mutex_enter(&esi
.esi_mutex
);
3182 idm_soshutdown(esi
.esi_so
);
3183 ksocket_rele(esi
.esi_so
);
3184 esi
.esi_valid
= B_FALSE
;
3187 * If we're going to try to re-establish the listener then
3188 * destroy this socket. Otherwise isnst_esi_stop already
3191 if (esi
.esi_enabled
)
3192 idm_sodestroy(esi
.esi_so
);
3195 esi
.esi_thread_running
= B_FALSE
;
3196 cv_signal(&esi
.esi_cv
);
3197 mutex_exit(&esi
.esi_mutex
);
3203 * Handle an incoming ESI request
3207 isnst_handle_esi_req(ksocket_t ks
, isns_pdu_t
*pdu
, size_t pdu_size
)
3209 isns_pdu_t
*rsp_pdu
;
3212 uint32_t attr_len
, attr_id
;
3213 size_t req_pl_len
, rsp_size
, tlv_len
;
3214 struct sockaddr_storage portal_ss
;
3215 struct sockaddr_storage server_ss
;
3216 struct sockaddr_in6
*portal_addr6
;
3217 boolean_t portal_addr_valid
= B_FALSE
;
3218 boolean_t portal_port_valid
= B_FALSE
;
3219 uint32_t esi_response
= ISNS_RSP_SUCCESSFUL
;
3220 isns_portal_t
*iportal
;
3224 if (ntohs(pdu
->func_id
) != ISNS_ESI
) {
3225 ISNST_LOG(CE_WARN
, "isnst_handle_esi_req: Unexpected func 0x%x",
3227 kmem_free(pdu
, pdu_size
);
3231 req_pl_len
= ntohs(pdu
->payload_len
);
3232 if (req_pl_len
+ offsetof(isns_pdu_t
, payload
) > pdu_size
) {
3233 ISNST_LOG(CE_WARN
, "isnst_handle_esi_req: "
3234 "payload exceeds PDU size (%d > %d)",
3235 (int)(req_pl_len
+ offsetof(isns_pdu_t
, payload
)),
3237 /* Not all data is present -- ignore */
3238 kmem_free(pdu
, pdu_size
);
3242 if (req_pl_len
+ sizeof (uint32_t) > ISNSP_MAX_PAYLOAD_SIZE
) {
3244 "isnst_handle_esi_req: PDU payload exceeds max (%ld bytes)",
3245 req_pl_len
+ sizeof (uint32_t));
3246 kmem_free(pdu
, pdu_size
);
3251 * Check portal in ESI request and make sure it is valid. Return
3252 * esi_response of ISNS_RSP_SUCCESSFUL if valid, otherwise don't
3253 * respond at all. Get IP addr and port. Format of ESI
3256 * ISNS_TIMESTAMP_ATTR_ID,
3258 * ISNS_PORTAL_IP_ADDR_ATTR_ID,
3259 * ISNS_PORTAL_PORT_ATTR_ID
3261 bzero(&portal_ss
, sizeof (struct sockaddr_storage
));
3262 portal_ss
.ss_family
= AF_INET6
;
3263 portal_addr6
= (struct sockaddr_in6
*)&portal_ss
;
3264 attr
= (isns_tlv_t
*)((void *)&pdu
->payload
);
3265 attr_len
= ntohl(attr
->attr_len
);
3266 attr_id
= ntohl(attr
->attr_id
);
3267 tlv_len
= attr_len
+ offsetof(isns_tlv_t
, attr_value
);
3268 while (tlv_len
<= req_pl_len
) {
3270 case ISNS_TIMESTAMP_ATTR_ID
:
3272 case ISNS_EID_ATTR_ID
:
3274 case ISNS_PORTAL_IP_ADDR_ATTR_ID
:
3275 if (attr_len
> sizeof (struct in6_addr
)) {
3276 /* Bad attribute format */
3277 esi_response
= ISNS_RSP_MSG_FORMAT_ERROR
;
3279 portal_addr6
->sin6_family
= AF_INET6
;
3280 attr_len
= min(attr_len
,
3281 sizeof (portal_addr6
->sin6_addr
));
3282 bcopy(attr
->attr_value
,
3283 portal_addr6
->sin6_addr
.s6_addr
, attr_len
);
3284 portal_addr_valid
= B_TRUE
;
3287 case ISNS_PORTAL_PORT_ATTR_ID
:
3288 if (attr_len
> sizeof (uint32_t)) {
3289 /* Bad attribute format */
3290 esi_response
= ISNS_RSP_MSG_FORMAT_ERROR
;
3292 portal_addr6
->sin6_port
=
3293 htons((uint16_t)BE_IN32(attr
->attr_value
));
3294 portal_port_valid
= B_TRUE
;
3298 /* Bad request format */
3299 esi_response
= ISNS_RSP_MSG_FORMAT_ERROR
;
3303 /* If we've set an error then stop processing */
3304 if (esi_response
!= ISNS_RSP_SUCCESSFUL
) {
3308 /* Get next attribute */
3309 req_pl_len
-= tlv_len
;
3310 attr
= (isns_tlv_t
*)((void *)((uint8_t *)attr
+ tlv_len
));
3311 attr_len
= ntohl(attr
->attr_len
);
3312 attr_id
= ntohl(attr
->attr_id
);
3313 tlv_len
= attr_len
+ offsetof(isns_tlv_t
, attr_value
);
3316 if (!portal_port_valid
)
3317 portal_addr6
->sin6_port
= htons(ISCSI_LISTEN_PORT
);
3319 if (!portal_addr_valid
) {
3320 esi_response
= ISNS_RSP_MSG_FORMAT_ERROR
;
3324 * If we've detected an error or if the portal does not
3325 * exist then drop the request. The server will eventually
3326 * timeout the portal and eliminate it from the list.
3329 if (esi_response
!= ISNS_RSP_SUCCESSFUL
) {
3330 kmem_free(pdu
, pdu_size
);
3334 /* Get the remote peer's IP address */
3335 bzero(&server_ss
, sizeof (server_ss
));
3336 sa_len
= sizeof (server_ss
);
3337 if (ksocket_getpeername(ks
, (struct sockaddr
*)&server_ss
, &sa_len
,
3342 if (iscsit_isns_logging
) {
3343 char server_buf
[IDM_SA_NTOP_BUFSIZ
];
3344 char portal_buf
[IDM_SA_NTOP_BUFSIZ
];
3345 ISNST_LOG(CE_NOTE
, "ESI: svr %s -> portal %s",
3346 idm_sa_ntop(&server_ss
, server_buf
,
3347 sizeof (server_buf
)),
3348 idm_sa_ntop(&portal_ss
, portal_buf
,
3349 sizeof (portal_buf
)));
3354 if (isnst_lookup_portal(&portal_ss
) == NULL
) {
3355 ISNST_LOG(CE_WARN
, "ESI req to non-active portal");
3356 ISNS_GLOBAL_UNLOCK();
3357 kmem_free(pdu
, pdu_size
);
3362 * Update the server timestamp of how recently we have
3363 * received an ESI request from this iSNS server.
3364 * We ignore requests from servers we don't know.
3366 if (! isnst_update_server_timestamp(&server_ss
)) {
3367 ISNST_LOG(CE_WARN
, "ESI req from unknown server");
3368 kmem_free(pdu
, pdu_size
);
3369 ISNS_GLOBAL_UNLOCK();
3374 * Update ESI timestamps for all portals with same IP address.
3376 for (iportal
= avl_first(&isns_all_portals
);
3378 iportal
= AVL_NEXT(&isns_all_portals
, iportal
)) {
3379 if (idm_ss_compare(&iportal
->portal_addr
, &portal_ss
,
3381 gethrestime(&iportal
->portal_esi_timestamp
);
3385 ISNS_GLOBAL_UNLOCK();
3389 * Build response validating the portal
3391 rsp_size
= isnst_create_pdu_header(ISNS_ESI_RSP
, &rsp_pdu
, 0);
3393 if (rsp_size
== 0) {
3394 ISNST_LOG(CE_WARN
, "isnst_handle_esi_req: Can't get rsp pdu");
3395 kmem_free(pdu
, pdu_size
);
3399 rsp
= (isns_resp_t
*)((void *)(&rsp_pdu
->payload
[0]));
3401 /* Use xid from the request pdu */
3402 rsp_pdu
->xid
= pdu
->xid
;
3403 rsp
->status
= htonl(ISNS_RSP_SUCCESSFUL
);
3405 /* Copy original data */
3406 req_pl_len
= ntohs(pdu
->payload_len
);
3407 bcopy(pdu
->payload
, rsp
->data
, req_pl_len
);
3408 rsp_pdu
->payload_len
= htons(req_pl_len
+ sizeof (uint32_t));
3410 if (isnst_send_pdu(ks
, rsp_pdu
) != 0) {
3412 "isnst_handle_esi_req: Send response failed");
3415 kmem_free(rsp_pdu
, rsp_size
);
3416 kmem_free(pdu
, pdu_size
);
3421 isnst_tgt_avl_compare(const void *t1
, const void *t2
)
3423 const isns_target_t
*tgt1
= t1
;
3424 const isns_target_t
*tgt2
= t2
;
3427 * Sort by target (pointer to iscsit_tgt_t).
3430 if (tgt1
->target
< tgt2
->target
) {
3432 } else if (tgt1
->target
> tgt2
->target
) {
3440 isnst_set_server_status(iscsit_isns_svr_t
*svr
, boolean_t registered
)
3442 isns_target_t
*itarget
;
3444 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3446 svr
->svr_reset_needed
= B_FALSE
;
3447 if (registered
== B_TRUE
) {
3448 svr
->svr_registered
= B_TRUE
;
3449 svr
->svr_last_msg
= ddi_get_lbolt();
3450 itarget
= avl_first(&svr
->svr_target_list
);
3452 isns_target_t
*next_target
;
3453 next_target
= AVL_NEXT(&svr
->svr_target_list
, itarget
);
3454 if (itarget
->target_delete_needed
) {
3455 /* All deleted tgts removed */
3456 isnst_clear_from_target_list(itarget
,
3457 &svr
->svr_target_list
);
3459 /* Other tgts marked registered */
3460 itarget
->target_registered
= B_TRUE
;
3461 /* No updates needed -- clean slate */
3462 itarget
->target_update_needed
= B_FALSE
;
3464 itarget
= next_target
;
3466 ASSERT(avl_numnodes(&svr
->svr_target_list
) > 0);
3468 svr
->svr_registered
= B_FALSE
;
3469 isnst_clear_target_list(svr
);
3474 isnst_monitor_default_portal_list(void)
3476 idm_addr_list_t
*new_portal_list
= NULL
;
3477 uint32_t new_portal_list_size
= 0;
3479 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3480 ASSERT(mutex_owned(&iscsit_isns_mutex
));
3482 if (default_portal_online
) {
3483 new_portal_list_size
= idm_get_ipaddr(&new_portal_list
);
3487 * We compute a new list of portals if
3488 * a) Something in itadm has changed a portal
3489 * b) there are new default portals
3490 * c) the default portal has gone offline
3492 if (isns_portals_changed
||
3493 ((new_portal_list_size
!= 0) &&
3494 (isnst_find_default_portals(new_portal_list
) !=
3495 num_default_portals
)) ||
3496 ((new_portal_list_size
== 0) && (num_default_portals
> 0))) {
3498 isnst_clear_default_portals();
3499 isnst_copy_portal_list(&isns_tpg_portals
,
3501 num_tpg_portals
= avl_numnodes(&isns_all_portals
);
3502 if (new_portal_list_size
!= 0) {
3503 num_default_portals
=
3504 isnst_add_default_portals(new_portal_list
);
3508 /* Catch any case where we miss an update to TPG portals */
3509 ASSERT(num_tpg_portals
== avl_numnodes(&isns_tpg_portals
));
3511 if (new_portal_list
!= NULL
) {
3512 kmem_free(new_portal_list
, new_portal_list_size
);
3518 isnst_find_default_portals(idm_addr_list_t
*alist
)
3520 idm_addr_t
*dportal
;
3521 isns_portal_t
*iportal
;
3522 struct sockaddr_storage sa
;
3524 int num_portals_found
= 0;
3526 for (aidx
= 0; aidx
< alist
->al_out_cnt
; aidx
++) {
3527 dportal
= &alist
->al_addrs
[aidx
];
3528 dportal
->a_port
= ISCSI_LISTEN_PORT
;
3529 idm_addr_to_sa(dportal
, &sa
);
3530 iportal
= isnst_lookup_portal(&sa
);
3531 if (iportal
== NULL
) {
3532 /* Found a non-matching default portal */
3535 if (iportal
->portal_default
) {
3536 num_portals_found
++;
3539 return (num_portals_found
);
3543 isnst_clear_default_portals(void)
3545 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3547 isnst_clear_portal_list(&isns_all_portals
);
3548 num_tpg_portals
= 0;
3549 num_default_portals
= 0;
3553 isnst_add_default_portals(idm_addr_list_t
*alist
)
3555 idm_addr_t
*dportal
;
3556 isns_portal_t
*iportal
;
3557 struct sockaddr_storage sa
;
3560 for (aidx
= 0; aidx
< alist
->al_out_cnt
; aidx
++) {
3561 dportal
= &alist
->al_addrs
[aidx
];
3562 dportal
->a_port
= ISCSI_LISTEN_PORT
;
3563 idm_addr_to_sa(dportal
, &sa
);
3564 iportal
= isnst_add_to_portal_list(&sa
, &isns_all_portals
);
3565 iportal
->portal_default
= B_TRUE
;
3567 return (alist
->al_out_cnt
);
3572 isnst_portal_avl_compare(const void *p1
, const void *p2
)
3574 const isns_portal_t
*portal1
= p1
;
3575 const isns_portal_t
*portal2
= p2
;
3577 return (idm_ss_compare(&portal1
->portal_addr
, &portal2
->portal_addr
,
3578 B_TRUE
/* v4_mapped_as_v4 */, B_TRUE
/* compare_ports */));
3582 isnst_clear_portal_list(avl_tree_t
*portal_list
)
3584 isns_portal_t
*iportal
;
3585 void *cookie
= NULL
;
3587 while ((iportal
= avl_destroy_nodes(portal_list
, &cookie
)) != NULL
) {
3588 kmem_free(iportal
, sizeof (isns_portal_t
));
3592 isnst_copy_portal_list(avl_tree_t
*t1
, avl_tree_t
*t2
)
3594 isns_portal_t
*iportal
, *jportal
;
3596 iportal
= (isns_portal_t
*)avl_first(t1
);
3598 jportal
= isnst_add_to_portal_list(&iportal
->portal_addr
, t2
);
3599 jportal
->portal_iscsit
= iportal
->portal_iscsit
;
3600 iportal
= AVL_NEXT(t1
, iportal
);
3605 static isns_portal_t
*
3606 isnst_lookup_portal(struct sockaddr_storage
*sa
)
3608 isns_portal_t
*iportal
, tmp_portal
;
3609 ASSERT(ISNS_GLOBAL_LOCK_HELD());
3611 bcopy(sa
, &tmp_portal
.portal_addr
, sizeof (*sa
));
3612 iportal
= avl_find(&isns_all_portals
, &tmp_portal
, NULL
);
3616 static isns_portal_t
*
3617 isnst_add_to_portal_list(struct sockaddr_storage
*sa
, avl_tree_t
*portal_list
)
3619 isns_portal_t
*iportal
, tmp_portal
;
3622 * Make sure this portal isn't already in our list.
3625 bcopy(sa
, &tmp_portal
.portal_addr
, sizeof (*sa
));
3627 if ((iportal
= (isns_portal_t
*)avl_find(portal_list
,
3628 &tmp_portal
, &where
)) == NULL
) {
3629 iportal
= kmem_zalloc(sizeof (isns_portal_t
), KM_SLEEP
);
3630 bcopy(sa
, &iportal
->portal_addr
, sizeof (*sa
));
3631 avl_insert(portal_list
, (void *)iportal
, where
);
3639 isnst_remove_from_portal_list(struct sockaddr_storage
*sa
,
3640 avl_tree_t
*portal_list
)
3642 isns_portal_t
*iportal
, tmp_portal
;
3644 bcopy(sa
, &tmp_portal
.portal_addr
, sizeof (*sa
));
3646 if ((iportal
= avl_find(portal_list
, &tmp_portal
, NULL
))
3648 avl_remove(portal_list
, iportal
);
3649 kmem_free(iportal
, sizeof (isns_portal_t
));
3654 * These functions are called by iscsit proper when a portal comes online
3659 iscsit_isns_portal_online(iscsit_portal_t
*portal
)
3661 isns_portal_t
*iportal
;
3663 mutex_enter(&iscsit_isns_mutex
);
3665 if (portal
->portal_default
) {
3666 /* Portals should only be onlined once */
3667 ASSERT(default_portal_online
== B_FALSE
);
3668 default_portal_online
= B_TRUE
;
3670 iportal
= isnst_add_to_portal_list(
3671 &portal
->portal_addr
, &isns_tpg_portals
);
3672 iportal
->portal_iscsit
= portal
;
3674 isns_portals_changed
= B_TRUE
;
3676 mutex_exit(&iscsit_isns_mutex
);
3678 isnst_monitor_awaken();
3682 iscsit_isns_portal_offline(iscsit_portal_t
*portal
)
3684 mutex_enter(&iscsit_isns_mutex
);
3686 if (portal
->portal_default
) {
3687 /* Portals should only be offlined once */
3688 ASSERT(default_portal_online
== B_TRUE
);
3689 default_portal_online
= B_FALSE
;
3691 isnst_remove_from_portal_list(&portal
->portal_addr
,
3694 isns_portals_changed
= B_TRUE
;
3696 mutex_exit(&iscsit_isns_mutex
);
3698 isnst_monitor_awaken();