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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2019 Joshua M. Clulow <josh@sysmgr.org>
24 */
25
26 /*
27 * ISCSID --
28 *
29 * Discovery of targets and access to the persistent storage starts here.
30 */
31
32 #include <sys/thread.h>
33 #include <sys/types.h>
34 #include <sys/proc.h> /* declares: p0 */
35 #include <sys/cmn_err.h>
36 #include <sys/scsi/adapters/iscsi_if.h>
37 #include <netinet/in.h>
38 #include "iscsi_targetparam.h"
39 #include "isns_client.h"
40 #include "isns_protocol.h"
41 #include "persistent.h"
42 #include "iscsi.h"
43 #include <sys/ethernet.h>
44 #include <sys/bootprops.h>
45
46 /*
47 * local function prototypes
48 */
49 static boolean_t iscsid_init_config(iscsi_hba_t *ihp);
50 static boolean_t iscsid_init_targets(iscsi_hba_t *ihp);
51 static void iscsid_thread_static(iscsi_thread_t *thread, void *p);
52 static void iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p);
53 static void iscsid_thread_isns(iscsi_thread_t *thread, void *p);
54 static void iscsid_thread_slp(iscsi_thread_t *thread, void *p);
55 static void iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p);
56 static void iscsid_threads_create(iscsi_hba_t *ihp);
57 static void iscsid_threads_destroy(void);
58 static int iscsid_copyto_param_set(uint32_t param_id,
59 iscsi_login_params_t *params, iscsi_param_set_t *ipsp);
60 static void iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
61 isns_portal_group_list_t *pg_list);
62 static void iscsid_remove_target_param(char *name);
63 static boolean_t iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
64 struct sockaddr *addr_dsc, char *target_name, int tpgt,
65 struct sockaddr *addr_tgt);
66 static void iscsi_discovery_event(iscsi_hba_t *ihp,
67 iSCSIDiscoveryMethod_t m, boolean_t start);
68 static boolean_t iscsid_boot_init_config(iscsi_hba_t *ihp);
69 static iscsi_sess_t *iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid);
70 static boolean_t iscsid_make_entry(ib_boot_prop_t *boot_prop_entry,
71 entry_t *entry);
72 static boolean_t iscsid_check_active_boot_conn(iscsi_hba_t *ihp);
73
74 extern int modrootloaded;
75 int iscsi_configroot_retry = 20;
76 static boolean_t iscsi_configroot_printed = FALSE;
77 static int iscsi_net_up = 0;
78 extern ib_boot_prop_t *iscsiboot_prop;
79
80 #define ISCSI_CONFIGROOT_DELAY 1
81
82 /*
83 * iSCSI target discovery thread table
84 */
85 typedef struct iscsid_thr_table {
86 void (*func_start)(iscsi_thread_t *, void *);
87 iscsi_thread_t *thr_id;
88 iSCSIDiscoveryMethod_t method;
89 char *name;
90 } iscsid_thr_table;
91
92 static iscsid_thr_table iscsid_thr[] = {
93 { iscsid_thread_static, NULL,
94 iSCSIDiscoveryMethodStatic,
95 "Static" },
96 { iscsid_thread_sendtgts, NULL,
97 iSCSIDiscoveryMethodSendTargets,
98 "SendTarget" },
99 { iscsid_thread_slp, NULL,
100 iSCSIDiscoveryMethodSLP,
101 "SLP" },
102 { iscsid_thread_isns, NULL,
103 iSCSIDiscoveryMethodISNS,
104 "iSNS" },
105 { NULL, NULL,
106 iSCSIDiscoveryMethodUnknown,
107 NULL }
108 };
109
110 /*
111 * discovery method event table
112 */
113 iSCSIDiscoveryMethod_t for_failure[] = {
114 iSCSIDiscoveryMethodStatic,
115 iSCSIDiscoveryMethodSLP,
116 iSCSIDiscoveryMethodISNS,
117 iSCSIDiscoveryMethodSendTargets,
118 iSCSIDiscoveryMethodUnknown /* terminating value */
119 };
120
121 /*
122 * The following private tunable, set in /etc/system, e.g.,
123 * set iscsi:iscsi_boot_max_delay = 360
124 * , provides with customer a max wait time in
125 * seconds to wait for boot lun online during iscsi boot.
126 * Defaults to 180s.
127 */
128 int iscsi_boot_max_delay = ISCSI_BOOT_DEFAULT_MAX_DELAY;
129
130 /*
131 * discovery configuration semaphore
132 */
133 ksema_t iscsid_config_semaphore;
134
135 static iscsi_thread_t *iscsi_boot_wd_handle = NULL;
136
137 #define CHECK_METHOD(v) ((dm & v) ? B_TRUE : B_FALSE)
138
139 /*
140 * Check if IP is valid
141 */
142 static boolean_t
iscsid_ip_check(char * ip)143 iscsid_ip_check(char *ip)
144 {
145 int i = 0;
146
147 if (!ip)
148 return (B_FALSE);
149 for (; (ip[i] == 0) && (i < IB_IP_BUFLEN); i++) {}
150 if (i == IB_IP_BUFLEN) {
151 /* invalid IP address */
152 return (B_FALSE);
153 }
154 return (B_TRUE);
155 }
156
157 /*
158 * Make an entry for the boot target.
159 * return B_TRUE upon success
160 * B_FALSE if fail
161 */
162 static boolean_t
iscsid_make_entry(ib_boot_prop_t * boot_prop_entry,entry_t * entry)163 iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, entry_t *entry)
164 {
165 if (entry == NULL || boot_prop_entry == NULL) {
166 return (B_FALSE);
167 }
168
169 if (!iscsid_ip_check(
170 (char *)&boot_prop_entry->boot_tgt.tgt_ip_u))
171 return (B_FALSE);
172
173 if (boot_prop_entry->boot_tgt.sin_family != AF_INET &&
174 boot_prop_entry->boot_tgt.sin_family != AF_INET6)
175 return (B_FALSE);
176
177 entry->e_vers = ISCSI_INTERFACE_VERSION;
178
179 mutex_enter(&iscsi_oid_mutex);
180 entry->e_oid = iscsi_oid++;
181 mutex_exit(&iscsi_oid_mutex);
182
183 entry->e_tpgt = ISCSI_DEFAULT_TPGT;
184
185 if (boot_prop_entry->boot_tgt.sin_family == AF_INET) {
186 entry->e_u.u_in4.s_addr =
187 boot_prop_entry->boot_tgt.tgt_ip_u.u_in4.s_addr;
188 entry->e_insize = sizeof (struct in_addr);
189 } else {
190 (void) bcopy(
191 &boot_prop_entry->boot_tgt.tgt_ip_u.u_in6.s6_addr,
192 entry->e_u.u_in6.s6_addr, 16);
193 entry->e_insize = sizeof (struct in6_addr);
194 }
195
196 entry->e_port = boot_prop_entry->boot_tgt.tgt_port;
197 entry->e_boot = B_TRUE;
198 return (B_TRUE);
199 }
200
201 /*
202 * Create the boot session
203 */
204 static void
iscsi_boot_session_create(iscsi_hba_t * ihp,ib_boot_prop_t * boot_prop_table)205 iscsi_boot_session_create(iscsi_hba_t *ihp,
206 ib_boot_prop_t *boot_prop_table)
207 {
208 iSCSIDiscoveryMethod_t dm;
209 entry_t e;
210 iscsi_sockaddr_t addr_dsc;
211
212 if (ihp == NULL || boot_prop_table == NULL) {
213 return;
214 }
215
216 if (!iscsid_ip_check(
217 (char *)&boot_prop_table->boot_tgt.tgt_ip_u)) {
218 return;
219 }
220
221 if (boot_prop_table->boot_tgt.tgt_name != NULL) {
222 dm = iSCSIDiscoveryMethodStatic |
223 iSCSIDiscoveryMethodBoot;
224 if (!iscsid_make_entry(boot_prop_table, &e))
225 return;
226 iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
227 e.e_port, &addr_dsc.sin);
228
229 (void) iscsid_add(ihp, dm, &addr_dsc.sin,
230 (char *)boot_prop_table->boot_tgt.tgt_name,
231 e.e_tpgt, &addr_dsc.sin);
232 } else {
233 dm = iSCSIDiscoveryMethodSendTargets |
234 iSCSIDiscoveryMethodBoot;
235 if (!iscsid_make_entry(boot_prop_table, &e))
236 return;
237 iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
238 e.e_port, &addr_dsc.sin);
239 iscsid_do_sendtgts(&e);
240 (void) iscsid_login_tgt(ihp, NULL, dm,
241 &addr_dsc.sin);
242 }
243 }
244
245 /*
246 * iscsid_init -- to initialize stuffs related to iscsi daemon,
247 * and to create boot session if needed
248 */
249 boolean_t
iscsid_init(iscsi_hba_t * ihp)250 iscsid_init(iscsi_hba_t *ihp)
251 {
252 boolean_t rval = B_TRUE;
253
254 sema_init(&iscsid_config_semaphore, 1, NULL,
255 SEMA_DRIVER, NULL);
256 persistent_init();
257 iscsid_threads_create(ihp);
258
259 if (modrootloaded) {
260 /*
261 * The root file system is available so we can load the
262 * persistent store.
263 */
264 if (persistent_load() == B_TRUE) {
265 ihp->hba_persistent_loaded = B_TRUE;
266 } else {
267 return (B_FALSE);
268 }
269 } else {
270 /*
271 * If the root file system is not yet mounted then we _must_ be
272 * booting from an iSCSI device. If not, we want to fail to
273 * attach so that we can try again after the VFS root is
274 * available.
275 */
276 if (iscsiboot_prop == NULL) {
277 return (B_FALSE);
278 }
279
280 if (!iscsid_boot_init_config(ihp)) {
281 rval = B_FALSE;
282 } else {
283 iscsi_boot_session_create(ihp, iscsiboot_prop);
284 iscsi_boot_wd_handle =
285 iscsi_thread_create(ihp->hba_dip,
286 "BootWD", iscsid_thread_boot_wd, ihp);
287 if (iscsi_boot_wd_handle != NULL) {
288 rval = iscsi_thread_start(
289 iscsi_boot_wd_handle);
290 } else {
291 rval = B_FALSE;
292 }
293 }
294 if (rval == B_FALSE) {
295 cmn_err(CE_NOTE, "Initializaton of iscsi boot session"
296 " partially failed");
297 }
298 }
299
300 return (rval);
301 }
302
303 /*
304 * iscsid_start -- start the iscsi initiator daemon, actually this code
305 * is just to enable discovery methods which are set enabled in
306 * persistent store, as an economic way to present the 'daemon' funtionality
307 */
308 boolean_t
iscsid_start(iscsi_hba_t * ihp)309 iscsid_start(iscsi_hba_t *ihp)
310 {
311 boolean_t rval = B_FALSE;
312 iSCSIDiscoveryMethod_t dm;
313 iSCSIDiscoveryMethod_t *fdm;
314
315 rval = iscsid_init_config(ihp);
316 if (rval == B_TRUE) {
317 rval = iscsid_init_targets(ihp);
318 }
319
320 if (rval == B_TRUE) {
321 dm = persistent_disc_meth_get();
322 rval = iscsid_enable_discovery(ihp, dm, B_TRUE);
323 if (rval == B_TRUE) {
324 iscsid_poke_discovery(ihp,
325 iSCSIDiscoveryMethodUnknown);
326 (void) iscsid_login_tgt(ihp, NULL,
327 iSCSIDiscoveryMethodUnknown, NULL);
328 }
329 }
330
331 if (rval == B_FALSE) {
332 /*
333 * In case of failure the events still need to be sent
334 * because the door daemon will pause until all these
335 * events have occurred.
336 */
337 for (fdm = &for_failure[0]; *fdm !=
338 iSCSIDiscoveryMethodUnknown; fdm++) {
339 /* ---- Send both start and end events ---- */
340 iscsi_discovery_event(ihp, *fdm, B_TRUE);
341 iscsi_discovery_event(ihp, *fdm, B_FALSE);
342 }
343 }
344
345 return (rval);
346 }
347
348 /*
349 * iscsid_stop -- stop the iscsi initiator daemon, by disabling
350 * all the discovery methods first, and then try to stop all
351 * related threads. This is a try-best effort, leave any 'busy' device
352 * (and therefore session) there and just return.
353 */
354 boolean_t
iscsid_stop(iscsi_hba_t * ihp)355 iscsid_stop(iscsi_hba_t *ihp)
356 {
357 boolean_t rval = B_FALSE;
358 iscsi_sess_t *isp = NULL;
359
360 (void) iscsid_disable_discovery(ihp, ISCSI_ALL_DISCOVERY_METHODS);
361
362 /* final check */
363 rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
364 if (ihp->hba_sess_list == NULL) {
365 rval = B_TRUE;
366 } else {
367 /*
368 * If only boot session is left, that is OK.
369 * Otherwise, we should report that some sessions are left.
370 */
371 rval = B_TRUE;
372 for (isp = ihp->hba_sess_list; isp != NULL;
373 isp = isp->sess_next) {
374 if (isp->sess_boot == B_FALSE) {
375 rval = B_FALSE;
376 break;
377 }
378 }
379 }
380 rw_exit(&ihp->hba_sess_list_rwlock);
381
382 return (rval);
383 }
384
385 /*
386 * iscsid_fini -- do whatever is required to clean up
387 */
388 /* ARGSUSED */
389 void
iscsid_fini()390 iscsid_fini()
391 {
392 if (iscsi_boot_wd_handle != NULL) {
393 iscsi_thread_destroy(iscsi_boot_wd_handle);
394 iscsi_boot_wd_handle = NULL;
395 }
396 iscsid_threads_destroy();
397 persistent_fini();
398 sema_destroy(&iscsid_config_semaphore);
399 }
400
401 /*
402 * iscsid_props -- returns discovery thread information, used by ioctl code
403 */
404 void
iscsid_props(iSCSIDiscoveryProperties_t * props)405 iscsid_props(iSCSIDiscoveryProperties_t *props)
406 {
407 iSCSIDiscoveryMethod_t dm;
408
409 dm = persistent_disc_meth_get();
410
411 props->vers = ISCSI_INTERFACE_VERSION;
412
413 /* ---- change once thread is implemented ---- */
414 props->iSNSDiscoverySettable = B_FALSE;
415 props->SLPDiscoverySettable = B_FALSE;
416 props->StaticDiscoverySettable = B_TRUE;
417 props->SendTargetsDiscoverySettable = B_TRUE;
418 props->iSNSDiscoveryMethod = iSNSDiscoveryMethodStatic;
419
420 props->iSNSDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodISNS);
421 props->StaticDiscoveryEnabled =
422 CHECK_METHOD(iSCSIDiscoveryMethodStatic);
423 props->SendTargetsDiscoveryEnabled =
424 CHECK_METHOD(iSCSIDiscoveryMethodSendTargets);
425 props->SLPDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodSLP);
426 }
427
428 /*
429 * iscsid_enable_discovery - start specified discovery methods
430 */
431 /* ARGSUSED */
432 boolean_t
iscsid_enable_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t idm,boolean_t poke)433 iscsid_enable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm,
434 boolean_t poke)
435 {
436 boolean_t rval = B_TRUE;
437 iscsid_thr_table *dt;
438
439 /*
440 * start the specified discovery method(s)
441 */
442 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
443 dt++) {
444 if (idm & dt->method) {
445 if (dt->thr_id != NULL) {
446 rval = iscsi_thread_start(dt->thr_id);
447 if (rval == B_FALSE) {
448 break;
449 }
450 if (poke == B_TRUE) {
451 (void) iscsi_thread_send_wakeup(
452 dt->thr_id);
453 }
454 } else {
455 /*
456 * unexpected condition. The threads for each
457 * discovery method should have started at
458 * initialization
459 */
460 ASSERT(B_FALSE);
461 }
462 }
463 } /* END for() */
464
465 return (rval);
466 }
467
468
469 /*
470 * iscsid_disable_discovery - stop specified discovery methods
471 */
472 boolean_t
iscsid_disable_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t idm)473 iscsid_disable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm)
474 {
475 boolean_t rval = B_TRUE;
476 iscsid_thr_table *dt;
477
478 /*
479 * stop the specified discovery method(s)
480 */
481 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
482 dt++) {
483 if (idm & dt->method) {
484
485 /* signal discovery event change - begin */
486 iscsi_discovery_event(ihp, dt->method, B_TRUE);
487
488 /* Attempt to logout of all associated targets */
489 rval = iscsid_del(ihp, NULL, dt->method, NULL);
490 if (rval == B_TRUE) {
491 /* Successfully logged out of targets */
492 if (dt->thr_id != NULL) {
493 rval = iscsi_thread_stop(dt->thr_id);
494 if (rval == B_FALSE) {
495 /*
496 * signal discovery
497 * event change - end
498 */
499 iscsi_discovery_event(ihp,
500 dt->method, B_FALSE);
501 break;
502 }
503
504 } else {
505 /*
506 * unexpected condition. The threads
507 * for each discovery method should
508 * have started at initialization
509 */
510 ASSERT(B_FALSE);
511 }
512 }
513
514 /* signal discovery event change - end */
515 iscsi_discovery_event(ihp, dt->method, B_FALSE);
516
517 }
518 } /* END for() */
519
520 return (rval);
521 }
522
523 /*
524 * iscsid_poke_discovery - wakeup discovery methods to find any new targets
525 * and wait for all discovery processes to complete.
526 */
527 void
iscsid_poke_discovery(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t method)528 iscsid_poke_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method)
529 {
530 #define ISCSI_DISCOVERY_DELAY 1
531
532 iSCSIDiscoveryMethod_t dm;
533 iscsid_thr_table *dt;
534 boolean_t send_wakeup;
535
536 ASSERT(ihp != NULL);
537
538 /* reset discovery flags */
539 mutex_enter(&ihp->hba_discovery_events_mutex);
540 ihp->hba_discovery_in_progress = B_TRUE;
541 ihp->hba_discovery_events = iSCSIDiscoveryMethodUnknown;
542 mutex_exit(&ihp->hba_discovery_events_mutex);
543
544 /* start all enabled discovery methods */
545 dm = persistent_disc_meth_get();
546 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
547 dt++) {
548 send_wakeup = B_FALSE;
549
550 if ((method == iSCSIDiscoveryMethodUnknown) ||
551 (method == dt->method)) {
552 if ((dm & dt->method) && (dt->thr_id != NULL)) {
553 if (iscsi_thread_send_wakeup(dt->thr_id) ==
554 B_TRUE) {
555 send_wakeup = B_TRUE;
556 }
557 }
558 }
559
560 if (send_wakeup == B_FALSE) {
561 iscsi_discovery_event(ihp, dt->method, B_TRUE);
562 iscsi_discovery_event(ihp, dt->method, B_FALSE);
563 }
564 }
565
566 mutex_enter(&ihp->hba_discovery_events_mutex);
567 while (ihp->hba_discovery_events != ISCSI_ALL_DISCOVERY_METHODS) {
568 mutex_exit(&ihp->hba_discovery_events_mutex);
569 delay(SEC_TO_TICK(ISCSI_DISCOVERY_DELAY));
570 mutex_enter(&ihp->hba_discovery_events_mutex);
571 }
572 ihp->hba_discovery_in_progress = B_FALSE;
573 mutex_exit(&ihp->hba_discovery_events_mutex);
574
575 }
576
577 /*
578 * iscsid_do_sendtgts - issue send targets command to the given discovery
579 * address and then add the discovered targets to the discovery queue
580 */
581 void
iscsid_do_sendtgts(entry_t * disc_addr)582 iscsid_do_sendtgts(entry_t *disc_addr)
583 {
584
585 #define SENDTGTS_DEFAULT_NUM_TARGETS 10
586
587 int stl_sz;
588 int stl_num_tgts = SENDTGTS_DEFAULT_NUM_TARGETS;
589 iscsi_sendtgts_list_t *stl_hdr = NULL;
590 boolean_t retry = B_TRUE;
591 char inp_buf[INET6_ADDRSTRLEN];
592 const char *ip;
593 int ctr;
594 int rc;
595 iscsi_hba_t *ihp;
596 iSCSIDiscoveryMethod_t dm = iSCSIDiscoveryMethodSendTargets;
597
598 /* allocate and initialize sendtargets list header */
599 stl_sz = sizeof (*stl_hdr) + ((stl_num_tgts - 1) *
600 sizeof (iscsi_sendtgts_entry_t));
601 stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
602
603 retry_sendtgts:
604 stl_hdr->stl_in_cnt = stl_num_tgts;
605 bcopy(disc_addr, &(stl_hdr->stl_entry),
606 sizeof (stl_hdr->stl_entry));
607 stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
608
609 /* lock interface so only one SendTargets operation occurs */
610 if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
611 cmn_err(CE_NOTE, "!iscsi discovery failure - SendTargets. "
612 "failure to get soft state");
613 kmem_free(stl_hdr, stl_sz);
614 return;
615 }
616 sema_p(&ihp->hba_sendtgts_semaphore);
617 rc = iscsi_ioctl_sendtgts_get(ihp, stl_hdr);
618 sema_v(&ihp->hba_sendtgts_semaphore);
619 if (rc) {
620 ip = inet_ntop((disc_addr->e_insize ==
621 sizeof (struct in_addr) ? AF_INET : AF_INET6),
622 &disc_addr->e_u, inp_buf, sizeof (inp_buf));
623 cmn_err(CE_NOTE,
624 "iscsi discovery failure - SendTargets (%s)\n", ip);
625 kmem_free(stl_hdr, stl_sz);
626 return;
627 }
628
629 /* check if all targets received */
630 if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
631 if (retry == B_TRUE) {
632 stl_num_tgts = stl_hdr->stl_out_cnt;
633 kmem_free(stl_hdr, stl_sz);
634 stl_sz = sizeof (*stl_hdr) +
635 ((stl_num_tgts - 1) *
636 sizeof (iscsi_sendtgts_entry_t));
637 stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
638 retry = B_FALSE;
639 goto retry_sendtgts;
640 } else {
641 ip = inet_ntop((disc_addr->e_insize ==
642 sizeof (struct in_addr) ?
643 AF_INET : AF_INET6), &disc_addr->e_u,
644 inp_buf, sizeof (inp_buf));
645 cmn_err(CE_NOTE, "iscsi discovery failure - "
646 "SendTargets overflow (%s)\n", ip);
647 kmem_free(stl_hdr, stl_sz);
648 return;
649 }
650 }
651
652 for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
653 iscsi_sockaddr_t addr_dsc;
654 iscsi_sockaddr_t addr_tgt;
655
656 iscsid_addr_to_sockaddr(disc_addr->e_insize,
657 &disc_addr->e_u, disc_addr->e_port, &addr_dsc.sin);
658 iscsid_addr_to_sockaddr(
659 stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize,
660 &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
661 stl_hdr->stl_list[ctr].ste_ipaddr.a_port,
662 &addr_tgt.sin);
663 if (disc_addr->e_boot == B_TRUE) {
664 dm = dm | iSCSIDiscoveryMethodBoot;
665 }
666 (void) iscsid_add(ihp, dm,
667 &addr_dsc.sin, (char *)stl_hdr->stl_list[ctr].ste_name,
668 stl_hdr->stl_list[ctr].ste_tpgt,
669 &addr_tgt.sin);
670 }
671 kmem_free(stl_hdr, stl_sz);
672 }
673
674 void
iscsid_do_isns_query_one_server(iscsi_hba_t * ihp,entry_t * isns_server)675 iscsid_do_isns_query_one_server(iscsi_hba_t *ihp, entry_t *isns_server)
676 {
677 int pg_sz, query_status;
678 iscsi_addr_t *ap;
679 isns_portal_group_list_t *pg_list;
680
681 ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
682 ap->a_port = isns_server->e_port;
683 ap->a_addr.i_insize = isns_server->e_insize;
684
685 if (isns_server->e_insize == sizeof (struct in_addr)) {
686 ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr);
687 } else if (isns_server->e_insize == sizeof (struct in6_addr)) {
688 bcopy(&(isns_server->e_u.u_in6.s6_addr),
689 ap->a_addr.i_addr.in6.s6_addr, 16);
690 } else {
691 kmem_free(ap, sizeof (iscsi_addr_t));
692 return;
693 }
694
695 pg_list = NULL;
696 query_status = isns_query_one_server(
697 ap, ihp->hba_isid,
698 ihp->hba_name, ihp->hba_alias,
699 ISNS_INITIATOR_NODE_TYPE, &pg_list);
700 kmem_free(ap, sizeof (iscsi_addr_t));
701 if (query_status != isns_ok || pg_list == NULL) {
702 DTRACE_PROBE1(iscsid_do_isns_query_one_server_status,
703 int, query_status);
704 return;
705 }
706
707 iscsid_add_pg_list_to_cache(ihp, pg_list);
708 pg_sz = sizeof (isns_portal_group_list_t);
709 if (pg_list->pg_out_cnt > 0) {
710 pg_sz += (pg_list->pg_out_cnt - 1) *
711 sizeof (isns_portal_group_t);
712 }
713 kmem_free(pg_list, pg_sz);
714 }
715
716 void
iscsid_do_isns_query(iscsi_hba_t * ihp)717 iscsid_do_isns_query(iscsi_hba_t *ihp)
718 {
719 int pg_sz, query_status;
720 isns_portal_group_list_t *pg_list;
721
722 pg_list = NULL;
723 query_status = isns_query(ihp->hba_isid,
724 ihp->hba_name,
725 ihp->hba_alias,
726 ISNS_INITIATOR_NODE_TYPE,
727 &pg_list);
728
729 if (pg_list == NULL) {
730 DTRACE_PROBE1(iscsid_do_isns_query_status,
731 int, query_status);
732 return;
733 }
734
735 if ((query_status != isns_ok &&
736 query_status != isns_op_partially_failed)) {
737 DTRACE_PROBE1(iscsid_do_isns_query_status,
738 int, query_status);
739 pg_sz = sizeof (isns_portal_group_list_t);
740 if (pg_list->pg_out_cnt > 0) {
741 pg_sz += (pg_list->pg_out_cnt - 1) *
742 sizeof (isns_portal_group_t);
743 }
744 kmem_free(pg_list, pg_sz);
745 return;
746 }
747
748 iscsid_add_pg_list_to_cache(ihp, pg_list);
749
750 pg_sz = sizeof (isns_portal_group_list_t);
751 if (pg_list->pg_out_cnt > 0) {
752 pg_sz += (pg_list->pg_out_cnt - 1) *
753 sizeof (isns_portal_group_t);
754 }
755 kmem_free(pg_list, pg_sz);
756 }
757
758 /*
759 * iscsid_config_one - for the given target name, attempt
760 * to login to all targets associated with name. If target
761 * name is not found in discovery queue, reset the discovery
762 * queue, kick the discovery processes, and then retry.
763 *
764 * NOTE: The caller of this function must hold the
765 * iscsid_config_semaphore across this call.
766 */
767 void
iscsid_config_one(iscsi_hba_t * ihp,char * name,boolean_t protect)768 iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect)
769 {
770 boolean_t rc = B_FALSE;
771 int retry = 0;
772 int lun_online = 0;
773 int cur_sec = 0;
774
775 if (!modrootloaded && (iscsiboot_prop != NULL)) {
776 if (!iscsi_configroot_printed) {
777 cmn_err(CE_NOTE, "Configuring"
778 " iSCSI boot session...");
779 iscsi_configroot_printed = B_TRUE;
780 }
781 if (iscsi_net_up == 0) {
782 if (iscsi_net_interface(B_FALSE) ==
783 ISCSI_STATUS_SUCCESS) {
784 iscsi_net_up = 1;
785 } else {
786 cmn_err(CE_WARN, "Failed to configure interface"
787 " for iSCSI boot session");
788 return;
789 }
790 }
791 while (rc == B_FALSE && retry <
792 iscsi_configroot_retry) {
793 rc = iscsid_login_tgt(ihp, name,
794 iSCSIDiscoveryMethodBoot, NULL);
795 if (rc == B_FALSE) {
796 /*
797 * create boot session
798 */
799 iscsi_boot_session_create(ihp,
800 iscsiboot_prop);
801 retry++;
802 continue;
803 }
804 rc = iscsid_check_active_boot_conn(ihp);
805 if (rc == B_FALSE) {
806 /*
807 * no active connection for the boot
808 * session, retry the login until
809 * one is found or the retry count
810 * is exceeded
811 */
812 delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
813 retry++;
814 continue;
815 }
816 /*
817 * The boot session has been created with active
818 * connection. If the target lun has not been online,
819 * we should wait here for a while
820 */
821 do {
822 lun_online =
823 iscsiboot_prop->boot_tgt.lun_online;
824 if (lun_online == 0) {
825 delay(SEC_TO_TICK(
826 ISCSI_CONFIGROOT_DELAY));
827 cur_sec++;
828 }
829 } while ((lun_online == 0) &&
830 (cur_sec < iscsi_boot_max_delay));
831 retry++;
832 }
833 if (!rc) {
834 cmn_err(CE_WARN, "Failed to configure iSCSI"
835 " boot session");
836 }
837 } else {
838 rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown,
839 NULL);
840 /*
841 * If we didn't login to the device we might have
842 * to update our discovery information and attempt
843 * the login again.
844 */
845 if (rc == B_FALSE) {
846 /*
847 * Stale /dev links can cause us to get floods
848 * of config requests. Prevent these repeated
849 * requests from causing unneeded discovery updates
850 * if ISCSI_CONFIG_STORM_PROTECT is set.
851 */
852 if ((protect == B_FALSE) ||
853 (ddi_get_lbolt() > ihp->hba_config_lbolt +
854 SEC_TO_TICK(ihp->hba_config_storm_delay))) {
855 ihp->hba_config_lbolt = ddi_get_lbolt();
856 iscsid_poke_discovery(ihp,
857 iSCSIDiscoveryMethodUnknown);
858 (void) iscsid_login_tgt(ihp, name,
859 iSCSIDiscoveryMethodUnknown, NULL);
860 }
861 }
862 }
863 }
864
865 /*
866 * iscsid_config_all - reset the discovery queue, kick the
867 * discovery processes, and login to all targets found
868 *
869 * NOTE: The caller of this function must hold the
870 * iscsid_config_semaphore across this call.
871 */
872 void
iscsid_config_all(iscsi_hba_t * ihp,boolean_t protect)873 iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect)
874 {
875 boolean_t rc = B_FALSE;
876 int retry = 0;
877 int lun_online = 0;
878 int cur_sec = 0;
879
880 if (!modrootloaded && iscsiboot_prop != NULL) {
881 if (!iscsi_configroot_printed) {
882 cmn_err(CE_NOTE, "Configuring"
883 " iSCSI boot session...");
884 iscsi_configroot_printed = B_TRUE;
885 }
886 if (iscsi_net_up == 0) {
887 if (iscsi_net_interface(B_FALSE) ==
888 ISCSI_STATUS_SUCCESS) {
889 iscsi_net_up = 1;
890 }
891 }
892 while (rc == B_FALSE && retry <
893 iscsi_configroot_retry) {
894 rc = iscsid_login_tgt(ihp, NULL,
895 iSCSIDiscoveryMethodBoot, NULL);
896 if (rc == B_FALSE) {
897 /*
898 * No boot session has been created.
899 * We would like to create the boot
900 * Session first.
901 */
902 iscsi_boot_session_create(ihp,
903 iscsiboot_prop);
904 retry++;
905 continue;
906 }
907 rc = iscsid_check_active_boot_conn(ihp);
908 if (rc == B_FALSE) {
909 /*
910 * no active connection for the boot
911 * session, retry the login until
912 * one is found or the retry count
913 * is exceeded
914 */
915 delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
916 retry++;
917 continue;
918 }
919 /*
920 * The boot session has been created with active
921 * connection. If the target lun has not been online,
922 * we should wait here for a while
923 */
924 do {
925 lun_online =
926 iscsiboot_prop->boot_tgt.lun_online;
927 if (lun_online == 0) {
928 delay(SEC_TO_TICK(
929 ISCSI_CONFIGROOT_DELAY));
930 cur_sec++;
931 }
932 } while ((lun_online == 0) &&
933 (cur_sec < iscsi_boot_max_delay));
934 retry++;
935 }
936 if (!rc) {
937 cmn_err(CE_WARN, "Failed to configure"
938 " boot session");
939 }
940 } else {
941 /*
942 * Stale /dev links can cause us to get floods
943 * of config requests. Prevent these repeated
944 * requests from causing unneeded discovery updates
945 * if ISCSI_CONFIG_STORM_PROTECT is set.
946 */
947 if ((protect == B_FALSE) ||
948 (ddi_get_lbolt() > ihp->hba_config_lbolt +
949 SEC_TO_TICK(ihp->hba_config_storm_delay))) {
950 ihp->hba_config_lbolt = ddi_get_lbolt();
951 iscsid_poke_discovery(ihp,
952 iSCSIDiscoveryMethodUnknown);
953 }
954 (void) iscsid_login_tgt(ihp, NULL,
955 iSCSIDiscoveryMethodUnknown, NULL);
956 }
957 }
958
959 /*
960 * isns_scn_callback - iSNS client received an SCN
961 *
962 * This code processes the iSNS client SCN events. These
963 * could relate to the addition, removal, or update of a
964 * logical unit.
965 */
966 void
isns_scn_callback(void * arg)967 isns_scn_callback(void *arg)
968 {
969 int i, pg_sz;
970 int qry_status;
971 isns_portal_group_list_t *pg_list;
972 uint32_t scn_type;
973 iscsi_hba_t *ihp;
974
975 if (arg == NULL) {
976 /* No argument */
977 return;
978 }
979
980 if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
981 kmem_free(arg, sizeof (isns_scn_callback_arg_t));
982 return;
983 }
984
985 /*
986 * All isns callbacks are from a standalone taskq
987 * therefore the blocking here doesn't affect the enable/disable
988 * of isns discovery method
989 */
990 if (iscsi_client_request_service(ihp) == B_FALSE) {
991 kmem_free(arg, sizeof (isns_scn_callback_arg_t));
992 return;
993 }
994
995 scn_type = ((isns_scn_callback_arg_t *)arg)->scn_type;
996 DTRACE_PROBE1(isns_scn_callback_scn_type, int, scn_type);
997 switch (scn_type) {
998 /*
999 * ISNS_OBJ_ADDED - An object has been added.
1000 */
1001 case ISNS_OBJ_ADDED:
1002 /* Query iSNS server for contact information */
1003 pg_list = NULL;
1004 qry_status = isns_query_one_node(
1005 ((isns_scn_callback_arg_t *)arg)->source_key_attr,
1006 ihp->hba_isid,
1007 ihp->hba_name,
1008 (uint8_t *)"",
1009 ISNS_INITIATOR_NODE_TYPE,
1010 &pg_list);
1011
1012 /* Verify portal group is found */
1013 if ((qry_status != isns_ok &&
1014 qry_status != isns_op_partially_failed) ||
1015 pg_list == NULL) {
1016 break;
1017 }
1018
1019 DTRACE_PROBE1(pg_list,
1020 isns_portal_group_list_t *, pg_list);
1021
1022 /* Add all portals for logical unit to discovery cache */
1023 for (i = 0; i < pg_list->pg_out_cnt; i++) {
1024 iscsi_sockaddr_t addr_dsc;
1025 iscsi_sockaddr_t addr_tgt;
1026
1027 iscsid_addr_to_sockaddr(
1028 pg_list->pg_list[i].isns_server_ip.i_insize,
1029 &pg_list->pg_list[i].isns_server_ip.i_addr,
1030 pg_list->pg_list[i].isns_server_port,
1031 &addr_dsc.sin);
1032 iscsid_addr_to_sockaddr(pg_list->pg_list[i].insize,
1033 &pg_list->pg_list[i].pg_ip_addr,
1034 pg_list->pg_list[i].pg_port, &addr_tgt.sin);
1035
1036 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS,
1037 &addr_dsc.sin, (char *)pg_list->pg_list[i].
1038 pg_iscsi_name, pg_list->pg_list[i].pg_tag,
1039 &addr_tgt.sin);
1040
1041 /* Force target to login */
1042 (void) iscsid_login_tgt(ihp, (char *)pg_list->
1043 pg_list[i].pg_iscsi_name, iSCSIDiscoveryMethodISNS,
1044 NULL);
1045 }
1046
1047 if (pg_list != NULL) {
1048 pg_sz = sizeof (isns_portal_group_list_t);
1049 if (pg_list->pg_out_cnt > 0) {
1050 pg_sz += (pg_list->pg_out_cnt - 1) *
1051 sizeof (isns_portal_group_t);
1052 }
1053 kmem_free(pg_list, pg_sz);
1054 }
1055 break;
1056
1057 /*
1058 * ISNS_OBJ_REMOVED - logical unit has been removed
1059 */
1060 case ISNS_OBJ_REMOVED:
1061 if (iscsid_del(ihp,
1062 (char *)((isns_scn_callback_arg_t *)arg)->
1063 source_key_attr, iSCSIDiscoveryMethodISNS, NULL) !=
1064 B_TRUE) {
1065 cmn_err(CE_NOTE, "iscsi initiator - "
1066 "isns remove scn failed for target %s\n",
1067 (char *)((isns_scn_callback_arg_t *)arg)->
1068 source_key_attr);
1069
1070 }
1071 break;
1072
1073 /*
1074 * ISNS_OBJ_UPDATED - logical unit has changed
1075 */
1076 case ISNS_OBJ_UPDATED:
1077 cmn_err(CE_NOTE, "iscsi initiator - "
1078 "received iSNS update SCN for %s\n",
1079 (char *)((isns_scn_callback_arg_t *)arg)->
1080 source_key_attr);
1081 break;
1082
1083 /*
1084 * ISNS_OBJ_UNKNOWN -
1085 */
1086 default:
1087 cmn_err(CE_NOTE, "iscsi initiator - "
1088 "received unknown iSNS SCN type 0x%x\n", scn_type);
1089 break;
1090 }
1091
1092 iscsi_client_release_service(ihp);
1093 kmem_free(arg, sizeof (isns_scn_callback_arg_t));
1094 }
1095
1096
1097 /*
1098 * iscsid_add - Creates discovered session and connection
1099 */
1100 static boolean_t
iscsid_add(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc,char * target_name,int tpgt,struct sockaddr * addr_tgt)1101 iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
1102 struct sockaddr *addr_dsc, char *target_name, int tpgt,
1103 struct sockaddr *addr_tgt)
1104 {
1105 boolean_t rtn = B_TRUE;
1106 iscsi_sess_t *isp;
1107 iscsi_conn_t *icp;
1108 uint_t oid;
1109 int idx;
1110 int isid;
1111 iscsi_config_sess_t *ics;
1112 int size;
1113 char *tmp;
1114
1115 ASSERT(ihp != NULL);
1116 ASSERT(addr_dsc != NULL);
1117 ASSERT(target_name != NULL);
1118 ASSERT(addr_tgt != NULL);
1119
1120 /* setup initial buffer for configured session information */
1121 size = sizeof (*ics);
1122 ics = kmem_zalloc(size, KM_SLEEP);
1123 ics->ics_in = 1;
1124
1125 /* get configured sessions information */
1126 tmp = target_name;
1127 if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1128 /*
1129 * No target information available check for
1130 * initiator information.
1131 */
1132 tmp = (char *)ihp->hba_name;
1133 if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1134 /*
1135 * No hba information is
1136 * found. So assume default
1137 * one session unbound behavior.
1138 */
1139 ics->ics_out = 1;
1140 ics->ics_bound = B_TRUE;
1141 }
1142 }
1143
1144 if (iscsiboot_prop && (ics->ics_out > 1) &&
1145 !iscsi_chk_bootlun_mpxio(ihp)) {
1146 /*
1147 * iscsi boot with mpxio disabled
1148 * no need to search configured boot session
1149 */
1150
1151 if (iscsi_cmp_boot_ini_name(tmp) ||
1152 iscsi_cmp_boot_tgt_name(tmp)) {
1153 ics->ics_out = 1;
1154 ics->ics_bound = B_FALSE;
1155 }
1156 }
1157 /* Check to see if we need to get more information */
1158 if (ics->ics_out > 1) {
1159 /* record new size and free last buffer */
1160 idx = ics->ics_out;
1161 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
1162 kmem_free(ics, sizeof (*ics));
1163
1164 /* allocate new buffer */
1165 ics = kmem_zalloc(size, KM_SLEEP);
1166 ics->ics_in = idx;
1167
1168 /* get configured sessions information */
1169 if (persistent_get_config_session(tmp, ics) != B_TRUE) {
1170 cmn_err(CE_NOTE, "iscsi session(%s) - "
1171 "unable to get configured session information\n",
1172 target_name);
1173 kmem_free(ics, size);
1174 return (B_FALSE);
1175 }
1176 }
1177
1178 /* loop for all configured sessions */
1179 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1180 for (isid = 0; isid < ics->ics_out; isid++) {
1181 /* create or find matching session */
1182 isp = iscsi_sess_create(ihp, method, addr_dsc, target_name,
1183 tpgt, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
1184 if (isp == NULL) {
1185 rtn = B_FALSE;
1186 break;
1187 }
1188
1189 /* create or find matching connection */
1190 if (!ISCSI_SUCCESS(iscsi_conn_create(addr_tgt, isp, &icp))) {
1191 /*
1192 * Teardown the session we just created. It can't
1193 * have any luns or connections associated with it
1194 * so this should always succeed (luckily since what
1195 * would we do if it failed?)
1196 */
1197 (void) iscsi_sess_destroy(isp);
1198 rtn = B_FALSE;
1199 break;
1200 }
1201 }
1202 rw_exit(&ihp->hba_sess_list_rwlock);
1203 kmem_free(ics, size);
1204 return (rtn);
1205 }
1206
1207 /*
1208 * iscsid_del - Attempts to delete all associated sessions
1209 */
1210 boolean_t
iscsid_del(iscsi_hba_t * ihp,char * target_name,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc)1211 iscsid_del(iscsi_hba_t *ihp, char *target_name,
1212 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1213 {
1214 boolean_t rtn = B_TRUE;
1215 iscsi_status_t status;
1216 iscsi_sess_t *isp;
1217 char name[ISCSI_MAX_NAME_LEN];
1218
1219 ASSERT(ihp != NULL);
1220 /* target name can be NULL or !NULL */
1221 /* addr_dsc can be NULL or !NULL */
1222
1223 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1224 isp = ihp->hba_sess_list;
1225 while (isp != NULL) {
1226 /*
1227 * If no target_name is listed (meaning all targets)
1228 * or this specific target was listed. And the same
1229 * discovery method discovered this target then
1230 * continue evaulation. Otherwise fail.
1231 */
1232 if (((target_name == NULL) ||
1233 (strcmp((char *)isp->sess_name, target_name) == 0)) &&
1234 (isp->sess_discovered_by == method)) {
1235 boolean_t try_destroy;
1236
1237 /*
1238 * If iSNS, SendTargets, or Static then special
1239 * handling for disc_addr.
1240 */
1241 if ((method == iSCSIDiscoveryMethodISNS) ||
1242 (method == iSCSIDiscoveryMethodSendTargets)) {
1243 /*
1244 * If NULL addr_dsc (meaning all disc_addr)
1245 * or matching discovered addr.
1246 */
1247 if ((addr_dsc == NULL) ||
1248 (bcmp(addr_dsc, &isp->sess_discovered_addr,
1249 SIZEOF_SOCKADDR(
1250 &isp->sess_discovered_addr.sin)) == 0)) {
1251 try_destroy = B_TRUE;
1252 } else {
1253 try_destroy = B_FALSE;
1254 }
1255 } else if (method == iSCSIDiscoveryMethodStatic) {
1256 /*
1257 * If NULL addr_dsc (meaning all disc_addr)
1258 * or matching active connection.
1259 */
1260 if ((addr_dsc == NULL) ||
1261 ((isp->sess_conn_act != NULL) &&
1262 (bcmp(addr_dsc,
1263 &isp->sess_conn_act->conn_base_addr.sin,
1264 SIZEOF_SOCKADDR(
1265 &isp->sess_conn_act->conn_base_addr.sin))
1266 == 0))) {
1267 try_destroy = B_TRUE;
1268 } else {
1269 try_destroy = B_FALSE;
1270 }
1271 } else {
1272 /* Unknown discovery specified */
1273 try_destroy = B_TRUE;
1274 }
1275
1276 if (try_destroy == B_TRUE &&
1277 isp->sess_boot == B_FALSE) {
1278 (void) strcpy(name, (char *)isp->sess_name);
1279 status = iscsi_sess_destroy(isp);
1280 if (ISCSI_SUCCESS(status)) {
1281 iscsid_remove_target_param(name);
1282 isp = ihp->hba_sess_list;
1283 } else if (status == ISCSI_STATUS_BUSY) {
1284 /*
1285 * The most likely destroy failure
1286 * is that ndi/mdi offline failed.
1287 * This means that the resource is
1288 * in_use/busy.
1289 */
1290 cmn_err(CE_NOTE, "iscsi session(%d) - "
1291 "resource is in use\n",
1292 isp->sess_oid);
1293 isp = isp->sess_next;
1294 rtn = B_FALSE;
1295 } else {
1296 cmn_err(CE_NOTE, "iscsi session(%d) - "
1297 "session logout failed (%d)\n",
1298 isp->sess_oid, status);
1299 isp = isp->sess_next;
1300 rtn = B_FALSE;
1301 }
1302 } else {
1303 isp = isp->sess_next;
1304 }
1305 } else {
1306 isp = isp->sess_next;
1307 }
1308 }
1309 rw_exit(&ihp->hba_sess_list_rwlock);
1310 return (rtn);
1311 }
1312
1313
1314 /*
1315 * iscsid_login_tgt - request target(s) to login
1316 */
1317 boolean_t
iscsid_login_tgt(iscsi_hba_t * ihp,char * target_name,iSCSIDiscoveryMethod_t method,struct sockaddr * addr_dsc)1318 iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
1319 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1320 {
1321 boolean_t rtn = B_FALSE;
1322 iscsi_sess_t *isp = NULL;
1323 iscsi_sess_list_t *isp_list = NULL;
1324 iscsi_sess_list_t *last_sess = NULL;
1325 iscsi_sess_list_t *cur_sess = NULL;
1326 int total = 0;
1327 ddi_taskq_t *login_taskq = NULL;
1328 char taskq_name[ISCSI_TH_MAX_NAME_LEN] = {0};
1329 time_t time_stamp;
1330
1331 ASSERT(ihp != NULL);
1332
1333 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1334 /* Loop thru sessions */
1335 isp = ihp->hba_sess_list;
1336 while (isp != NULL) {
1337 boolean_t try_online;
1338 if (!(method & iSCSIDiscoveryMethodBoot)) {
1339 if (target_name == NULL) {
1340 if (method == iSCSIDiscoveryMethodUnknown) {
1341 /* unknown method mean login to all */
1342 try_online = B_TRUE;
1343 } else if (isp->sess_discovered_by & method) {
1344 if ((method ==
1345 iSCSIDiscoveryMethodISNS) ||
1346 (method ==
1347 iSCSIDiscoveryMethodSendTargets)) {
1348 #define SESS_DISC_ADDR isp->sess_discovered_addr.sin
1349 if ((addr_dsc == NULL) ||
1350 (bcmp(
1351 &isp->sess_discovered_addr,
1352 addr_dsc, SIZEOF_SOCKADDR(
1353 &SESS_DISC_ADDR))
1354 == 0)) {
1355 /*
1356 * iSNS or sendtarget
1357 * discovery and
1358 * discovery address
1359 * is NULL or match
1360 */
1361 try_online = B_TRUE;
1362 } else {
1363 /* addr_dsc not a match */
1364 try_online = B_FALSE;
1365 }
1366 #undef SESS_DISC_ADDR
1367 } else {
1368 /* static configuration */
1369 try_online = B_TRUE;
1370 }
1371 } else {
1372 /* method not a match */
1373 try_online = B_FALSE;
1374 }
1375 } else if (strcmp(target_name,
1376 (char *)isp->sess_name) == 0) {
1377 /* target_name match */
1378 try_online = B_TRUE;
1379 } else {
1380 /* target_name not a match */
1381 try_online = B_FALSE;
1382 }
1383 } else {
1384 /*
1385 * online the boot session.
1386 */
1387 if (isp->sess_boot == B_TRUE) {
1388 try_online = B_TRUE;
1389 }
1390 }
1391
1392 if (try_online == B_TRUE &&
1393 isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1394 total++;
1395 /* Copy these sessions to the list. */
1396 if (isp_list == NULL) {
1397 isp_list =
1398 (iscsi_sess_list_t *)kmem_zalloc(
1399 sizeof (iscsi_sess_list_t), KM_SLEEP);
1400 last_sess = isp_list;
1401 last_sess->session = isp;
1402 last_sess->next = NULL;
1403 } else {
1404 last_sess->next =
1405 (iscsi_sess_list_t *)kmem_zalloc(
1406 sizeof (iscsi_sess_list_t), KM_SLEEP);
1407 last_sess->next->session = isp;
1408 last_sess->next->next = NULL;
1409 last_sess = last_sess->next;
1410 }
1411 rtn = B_TRUE;
1412 }
1413
1414 isp = isp->sess_next;
1415 }
1416
1417 if (total > 0) {
1418 time_stamp = ddi_get_time();
1419 (void) snprintf(taskq_name, (ISCSI_TH_MAX_NAME_LEN - 1),
1420 "login_queue.%lx", time_stamp);
1421
1422 login_taskq = ddi_taskq_create(ihp->hba_dip,
1423 taskq_name, total, TASKQ_DEFAULTPRI, 0);
1424 if (login_taskq == NULL) {
1425 while (isp_list != NULL) {
1426 cur_sess = isp_list;
1427 isp_list = isp_list->next;
1428 kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1429 }
1430 rtn = B_FALSE;
1431 rw_exit(&ihp->hba_sess_list_rwlock);
1432 return (rtn);
1433 }
1434
1435 for (cur_sess = isp_list; cur_sess != NULL;
1436 cur_sess = cur_sess->next) {
1437 if (ddi_taskq_dispatch(login_taskq,
1438 iscsi_sess_online, (void *)cur_sess->session,
1439 DDI_SLEEP) != DDI_SUCCESS) {
1440 cmn_err(CE_NOTE, "Can't dispatch the task "
1441 "for login to the target: %s",
1442 cur_sess->session->sess_name);
1443 }
1444 }
1445
1446 ddi_taskq_wait(login_taskq);
1447 ddi_taskq_destroy(login_taskq);
1448 while (isp_list != NULL) {
1449 cur_sess = isp_list;
1450 isp_list = isp_list->next;
1451 kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1452 }
1453
1454 }
1455
1456 rw_exit(&ihp->hba_sess_list_rwlock);
1457 return (rtn);
1458 }
1459
1460 /*
1461 * +--------------------------------------------------------------------+
1462 * | Local Helper Functions |
1463 * +--------------------------------------------------------------------+
1464 */
1465
1466 /*
1467 * iscsid_init_config -- initialize configuration parameters of iSCSI initiator
1468 */
1469 static boolean_t
iscsid_init_config(iscsi_hba_t * ihp)1470 iscsid_init_config(iscsi_hba_t *ihp)
1471 {
1472 iscsi_param_set_t ips;
1473 void *v = NULL;
1474 char *name;
1475 char *initiatorName;
1476 persistent_param_t pp;
1477 persistent_tunable_param_t pparam;
1478 uint32_t param_id;
1479 int rc;
1480
1481 /* allocate memory to hold initiator names */
1482 initiatorName = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1483
1484 /*
1485 * initialize iSCSI initiator name
1486 */
1487 bzero(&ips, sizeof (ips));
1488 if (persistent_initiator_name_get(initiatorName,
1489 ISCSI_MAX_NAME_LEN) == B_TRUE) {
1490 ips.s_vers = ISCSI_INTERFACE_VERSION;
1491 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
1492
1493 if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) {
1494 (void) strncpy(initiatorName,
1495 (const char *)iscsiboot_prop->boot_init.ini_name,
1496 ISCSI_MAX_NAME_LEN);
1497 (void) strncpy((char *)ips.s_value.v_name,
1498 (const char *)iscsiboot_prop->boot_init.ini_name,
1499 sizeof (ips.s_value.v_name));
1500 (void) iscsi_set_params(&ips, ihp, B_TRUE);
1501 /* use default tunable value */
1502 ihp->hba_tunable_params.recv_login_rsp_timeout =
1503 ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1504 ihp->hba_tunable_params.polling_login_delay =
1505 ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1506 ihp->hba_tunable_params.conn_login_max =
1507 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
1508 cmn_err(CE_NOTE, "Set initiator's name"
1509 " from firmware");
1510 } else {
1511 (void) strncpy((char *)ips.s_value.v_name,
1512 initiatorName, sizeof (ips.s_value.v_name));
1513
1514 (void) iscsi_set_params(&ips, ihp, B_FALSE);
1515 if (persistent_get_tunable_param(initiatorName,
1516 &pparam) == B_FALSE) {
1517 /* use default value */
1518 pparam.p_params.recv_login_rsp_timeout =
1519 ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1520 pparam.p_params.polling_login_delay =
1521 ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1522 pparam.p_params.conn_login_max =
1523 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
1524 }
1525 bcopy(&pparam.p_params, &ihp->hba_tunable_params,
1526 sizeof (iscsi_tunable_params_t));
1527 }
1528 } else {
1529 /*
1530 * if no initiator-node name available it is most
1531 * likely due to a fresh install, or the persistent
1532 * store is not working correctly. Set
1533 * a default initiator name so that the initiator can
1534 * be brought up properly.
1535 */
1536 iscsid_set_default_initiator_node_settings(ihp, B_FALSE);
1537 (void) strncpy(initiatorName, (const char *)ihp->hba_name,
1538 ISCSI_MAX_NAME_LEN);
1539 }
1540
1541 /*
1542 * initialize iSCSI initiator alias (if any)
1543 */
1544 bzero(&ips, sizeof (ips));
1545 if (persistent_alias_name_get((char *)ips.s_value.v_name,
1546 sizeof (ips.s_value.v_name)) == B_TRUE) {
1547 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
1548 (void) iscsi_set_params(&ips, ihp, B_FALSE);
1549 } else {
1550 /* EMPTY */
1551 /* No alias defined - not a problem. */
1552 }
1553
1554 /*
1555 * load up the overriden iSCSI initiator parameters
1556 */
1557 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1558 persistent_param_lock();
1559 v = NULL;
1560 while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1561 if (strncmp(name, initiatorName, ISCSI_MAX_NAME_LEN) == 0) {
1562 ips.s_oid = ihp->hba_oid;
1563 ips.s_vers = ISCSI_INTERFACE_VERSION;
1564 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1565 param_id++) {
1566 if (pp.p_bitmap & (1 << param_id)) {
1567 rc = iscsid_copyto_param_set(param_id,
1568 &pp.p_params, &ips);
1569 if (rc == 0) {
1570 rc = iscsi_set_params(&ips,
1571 ihp, B_FALSE);
1572 }
1573 if (rc != 0) {
1574 /* note error but continue */
1575 cmn_err(CE_NOTE,
1576 "Failed to set "
1577 "param %d for OID %d",
1578 ips.s_param, ips.s_oid);
1579 }
1580 }
1581 } /* END for() */
1582 if (iscsiboot_prop &&
1583 iscsi_chk_bootlun_mpxio(ihp)) {
1584 (void) iscsi_reconfig_boot_sess(ihp);
1585 }
1586 break;
1587 }
1588 } /* END while() */
1589 persistent_param_unlock();
1590
1591 kmem_free(initiatorName, ISCSI_MAX_NAME_LEN);
1592 kmem_free(name, ISCSI_MAX_NAME_LEN);
1593 return (B_TRUE);
1594 }
1595
1596
1597 /*
1598 * iscsid_init_targets -- Load up the driver with known static targets and
1599 * targets whose parameters have been modified.
1600 *
1601 * This is done so that the CLI can find a list of targets the driver
1602 * currently knows about.
1603 *
1604 * The driver doesn't need to log into these targets. Log in is done based
1605 * upon the enabled discovery methods.
1606 */
1607 static boolean_t
iscsid_init_targets(iscsi_hba_t * ihp)1608 iscsid_init_targets(iscsi_hba_t *ihp)
1609 {
1610 void *v = NULL;
1611 char *name;
1612 iscsi_param_set_t ips;
1613 persistent_param_t pp;
1614 char *iname;
1615 uint32_t param_id;
1616 int rc;
1617
1618 ASSERT(ihp != NULL);
1619
1620 /* allocate memory to hold target names */
1621 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1622
1623 /*
1624 * load up targets whose parameters have been overriden
1625 */
1626
1627 /* ---- only need to be set once ---- */
1628 bzero(&ips, sizeof (ips));
1629 ips.s_vers = ISCSI_INTERFACE_VERSION;
1630
1631 /* allocate memory to hold initiator name */
1632 iname = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1633 (void) persistent_initiator_name_get(iname, ISCSI_MAX_NAME_LEN);
1634
1635 persistent_param_lock();
1636 v = NULL;
1637 while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1638
1639 if (strncmp(iname, name, ISCSI_MAX_NAME_LEN) == 0) {
1640 /*
1641 * target name matched initiator's name so,
1642 * continue to next target. Initiator's
1643 * parmeters have already been set.
1644 */
1645 continue;
1646 }
1647
1648 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
1649 !iscsi_chk_bootlun_mpxio(ihp)) {
1650 /*
1651 * boot target is not mpxio enabled
1652 * simply ignore these overriden parameters
1653 */
1654 continue;
1655 }
1656
1657 ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name);
1658
1659 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1660 param_id++) {
1661 if (pp.p_bitmap & (1 << param_id)) {
1662 rc = iscsid_copyto_param_set(param_id,
1663 &pp.p_params, &ips);
1664 if (rc == 0) {
1665 rc = iscsi_set_params(&ips,
1666 ihp, B_FALSE);
1667 }
1668 if (rc != 0) {
1669 /* note error but continue ---- */
1670 cmn_err(CE_NOTE, "Failed to set "
1671 "param %d for OID %d",
1672 ips.s_param, ips.s_oid);
1673 }
1674 }
1675 } /* END for() */
1676 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
1677 iscsi_chk_bootlun_mpxio(ihp)) {
1678 (void) iscsi_reconfig_boot_sess(ihp);
1679 }
1680 } /* END while() */
1681 persistent_param_unlock();
1682
1683 kmem_free(iname, ISCSI_MAX_NAME_LEN);
1684 kmem_free(name, ISCSI_MAX_NAME_LEN);
1685
1686 return (B_TRUE);
1687 }
1688
1689
1690 /*
1691 * iscsid_thread_static -- If static discovery is enabled, this routine obtains
1692 * all statically configured targets from the peristent store and issues a
1693 * login request to the driver.
1694 */
1695 /* ARGSUSED */
1696 static void
iscsid_thread_static(iscsi_thread_t * thread,void * p)1697 iscsid_thread_static(iscsi_thread_t *thread, void *p)
1698 {
1699 iSCSIDiscoveryMethod_t dm;
1700 entry_t entry;
1701 char name[ISCSI_MAX_NAME_LEN];
1702 void *v = NULL;
1703 iscsi_hba_t *ihp = (iscsi_hba_t *)p;
1704
1705 while (iscsi_thread_wait(thread, -1) != 0) {
1706 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_TRUE);
1707
1708 /* ---- ensure static target discovery is enabled ---- */
1709 dm = persistent_disc_meth_get();
1710 if ((dm & iSCSIDiscoveryMethodStatic) == 0) {
1711 cmn_err(CE_NOTE,
1712 "iscsi discovery failure - "
1713 "StaticTargets method is not enabled");
1714 iscsi_discovery_event(ihp,
1715 iSCSIDiscoveryMethodStatic, B_FALSE);
1716 continue;
1717 }
1718
1719 /*
1720 * walk list of the statically configured targets from the
1721 * persistent store
1722 */
1723 v = NULL;
1724 persistent_static_addr_lock();
1725 while (persistent_static_addr_next(&v, name, &entry) ==
1726 B_TRUE) {
1727 iscsi_sockaddr_t addr;
1728
1729 iscsid_addr_to_sockaddr(entry.e_insize,
1730 &(entry.e_u), entry.e_port, &addr.sin);
1731
1732 (void) iscsid_add(ihp, iSCSIDiscoveryMethodStatic,
1733 &addr.sin, name, entry.e_tpgt, &addr.sin);
1734 }
1735 persistent_static_addr_unlock();
1736 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_FALSE);
1737 }
1738 }
1739
1740
1741 /*
1742 * iscsid_thread_sendtgts -- If SendTargets discovery is enabled, this routine
1743 * obtains all target discovery addresses configured from the peristent store
1744 * and probe the IP/port addresses for possible targets. It will then issue
1745 * a login request to the driver for all discoveryed targets.
1746 */
1747 static void
iscsid_thread_sendtgts(iscsi_thread_t * thread,void * p)1748 iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p)
1749 {
1750 iscsi_hba_t *ihp = (iscsi_hba_t *)p;
1751 iSCSIDiscoveryMethod_t dm;
1752 entry_t entry;
1753 void *v = NULL;
1754
1755 while (iscsi_thread_wait(thread, -1) != 0) {
1756 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1757 B_TRUE);
1758
1759 /* ---- ensure SendTargets discovery is enabled ---- */
1760 dm = persistent_disc_meth_get();
1761 if ((dm & iSCSIDiscoveryMethodSendTargets) == 0) {
1762 cmn_err(CE_NOTE,
1763 "iscsi discovery failure - "
1764 "SendTargets method is not enabled");
1765 iscsi_discovery_event(ihp,
1766 iSCSIDiscoveryMethodSendTargets, B_FALSE);
1767 continue;
1768 }
1769 /*
1770 * walk list of the SendTarget discovery addresses from the
1771 * persistent store
1772 */
1773 v = NULL;
1774 persistent_disc_addr_lock();
1775 while (persistent_disc_addr_next(&v, &entry) == B_TRUE) {
1776 iscsid_do_sendtgts(&entry);
1777 }
1778 persistent_disc_addr_unlock();
1779
1780 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1781 B_FALSE);
1782 }
1783 }
1784
1785 /*
1786 * iscsid_thread_slp -- If SLP discovery is enabled, this routine provides
1787 * the SLP discovery service.
1788 */
1789 static void
iscsid_thread_slp(iscsi_thread_t * thread,void * p)1790 iscsid_thread_slp(iscsi_thread_t *thread, void *p)
1791 {
1792 iscsi_hba_t *ihp = (iscsi_hba_t *)p;
1793
1794 do {
1795 /*
1796 * Even though we don't have support for SLP at this point
1797 * we'll send the events if someone has enabled this thread.
1798 * If this is not done the daemon waiting for discovery to
1799 * complete will pause forever holding up the boot process.
1800 */
1801 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_TRUE);
1802 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_FALSE);
1803 } while (iscsi_thread_wait(thread, -1) != 0);
1804 }
1805
1806 /*
1807 * iscsid_thread_isns --
1808 */
1809 static void
iscsid_thread_isns(iscsi_thread_t * thread,void * ptr)1810 iscsid_thread_isns(iscsi_thread_t *thread, void *ptr)
1811 {
1812 iscsi_hba_t *ihp = (iscsi_hba_t *)ptr;
1813 iSCSIDiscoveryMethod_t dm;
1814
1815 while (iscsi_thread_wait(thread, -1) != 0) {
1816 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_TRUE);
1817
1818 /* ---- ensure iSNS discovery is enabled ---- */
1819 dm = persistent_disc_meth_get();
1820 if ((dm & iSCSIDiscoveryMethodISNS) == 0) {
1821 cmn_err(CE_NOTE,
1822 "iscsi discovery failure - "
1823 "iSNS method is not enabled");
1824 iscsi_discovery_event(ihp,
1825 iSCSIDiscoveryMethodISNS, B_FALSE);
1826 continue;
1827 }
1828
1829 (void) isns_reg(ihp->hba_isid,
1830 ihp->hba_name,
1831 ISCSI_MAX_NAME_LEN,
1832 ihp->hba_alias,
1833 ISCSI_MAX_NAME_LEN,
1834 ISNS_INITIATOR_NODE_TYPE,
1835 isns_scn_callback);
1836 iscsid_do_isns_query(ihp);
1837 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_FALSE);
1838 }
1839
1840 /* Thread stopped. Deregister from iSNS servers(s). */
1841 (void) isns_dereg(ihp->hba_isid, ihp->hba_name);
1842 }
1843
1844
1845 /*
1846 * iscsid_threads_create -- Creates all the discovery threads.
1847 */
1848 static void
iscsid_threads_create(iscsi_hba_t * ihp)1849 iscsid_threads_create(iscsi_hba_t *ihp)
1850 {
1851 iscsid_thr_table *t;
1852
1853 /*
1854 * start a thread for each discovery method
1855 */
1856 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1857 t++) {
1858 if (t->thr_id == NULL) {
1859 t->thr_id = iscsi_thread_create(ihp->hba_dip, t->name,
1860 t->func_start, ihp);
1861 }
1862 }
1863 }
1864
1865 /*
1866 * iscsid_threads_destroy -- Destroys all the discovery threads.
1867 */
1868 static void
iscsid_threads_destroy(void)1869 iscsid_threads_destroy(void)
1870 {
1871 iscsid_thr_table *t;
1872
1873 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1874 t++) {
1875 if (t->thr_id != NULL) {
1876 iscsi_thread_destroy(t->thr_id);
1877 t->thr_id = NULL;
1878 }
1879 }
1880 }
1881
1882 /*
1883 * iscsid_copyto_param_set - helper function for iscsid_init_params.
1884 */
1885 static int
iscsid_copyto_param_set(uint32_t param_id,iscsi_login_params_t * params,iscsi_param_set_t * ipsp)1886 iscsid_copyto_param_set(uint32_t param_id, iscsi_login_params_t *params,
1887 iscsi_param_set_t *ipsp)
1888 {
1889 int rtn = 0;
1890
1891 if (param_id >= ISCSI_NUM_LOGIN_PARAM) {
1892 return (EINVAL);
1893 }
1894
1895 switch (param_id) {
1896
1897 /*
1898 * Boolean parameters
1899 */
1900 case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER:
1901 ipsp->s_value.v_bool = params->data_pdu_in_order;
1902 break;
1903 case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA:
1904 ipsp->s_value.v_bool = params->immediate_data;
1905 break;
1906 case ISCSI_LOGIN_PARAM_INITIAL_R2T:
1907 ipsp->s_value.v_bool = params->initial_r2t;
1908 break;
1909 case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER:
1910 ipsp->s_value.v_bool = params->data_pdu_in_order;
1911 break;
1912
1913 /*
1914 * Integer parameters
1915 */
1916 case ISCSI_LOGIN_PARAM_HEADER_DIGEST:
1917 ipsp->s_value.v_integer = params->header_digest;
1918 break;
1919 case ISCSI_LOGIN_PARAM_DATA_DIGEST:
1920 ipsp->s_value.v_integer = params->data_digest;
1921 break;
1922 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN:
1923 ipsp->s_value.v_integer = params->default_time_to_retain;
1924 break;
1925 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT:
1926 ipsp->s_value.v_integer = params->default_time_to_wait;
1927 break;
1928 case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH:
1929 ipsp->s_value.v_integer = params->max_recv_data_seg_len;
1930 break;
1931 case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH:
1932 ipsp->s_value.v_integer = params->first_burst_length;
1933 break;
1934 case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH:
1935 ipsp->s_value.v_integer = params->max_burst_length;
1936 break;
1937
1938 /*
1939 * Integer parameters which currently are unsettable
1940 */
1941 case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS:
1942 case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T:
1943 case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL:
1944 /* ---- drop through to default case ---- */
1945 default:
1946 rtn = EINVAL;
1947 break;
1948 }
1949
1950 /* if all is well, set the parameter identifier */
1951 if (rtn == 0) {
1952 ipsp->s_param = param_id;
1953 }
1954
1955 return (rtn);
1956 }
1957
1958 /*
1959 * iscsid_add_pg_list_to_cache - Add portal groups in the list to the
1960 * discovery cache.
1961 */
1962 static void
iscsid_add_pg_list_to_cache(iscsi_hba_t * ihp,isns_portal_group_list_t * pg_list)1963 iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
1964 isns_portal_group_list_t *pg_list)
1965 {
1966 int i;
1967
1968 for (i = 0; i < pg_list->pg_out_cnt; i++) {
1969 iscsi_sockaddr_t addr_dsc;
1970 iscsi_sockaddr_t addr_tgt;
1971
1972 iscsid_addr_to_sockaddr(
1973 pg_list->pg_list[i].isns_server_ip.i_insize,
1974 &pg_list->pg_list[i].isns_server_ip.i_addr,
1975 pg_list->pg_list[i].isns_server_port,
1976 &addr_dsc.sin);
1977 iscsid_addr_to_sockaddr(
1978 pg_list->pg_list[i].insize,
1979 &pg_list->pg_list[i].pg_ip_addr,
1980 pg_list->pg_list[i].pg_port,
1981 &addr_tgt.sin);
1982
1983 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, &addr_dsc.sin,
1984 (char *)pg_list->pg_list[i].pg_iscsi_name,
1985 pg_list->pg_list[i].pg_tag, &addr_tgt.sin);
1986 }
1987 }
1988
1989 /*
1990 * set_initiator_name - set default initiator name and alias.
1991 *
1992 * This sets the default initiator name and alias. The
1993 * initiator name is composed of sun's reverse domain name
1994 * and registration followed and a unique classifier. This
1995 * classifier is the mac address of the first NIC in the
1996 * host and a timestamp to make sure the classifier is
1997 * unique if the NIC is moved between hosts. The alias
1998 * is just the hostname.
1999 */
2000 void
iscsid_set_default_initiator_node_settings(iscsi_hba_t * ihp,boolean_t minimal)2001 iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp, boolean_t minimal)
2002 {
2003 int i;
2004 time_t x;
2005 struct ether_addr eaddr;
2006 char val[10];
2007 iscsi_chap_props_t *chap = NULL;
2008
2009 /* Set default initiator-node name */
2010 if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) {
2011 (void) strncpy((char *)ihp->hba_name,
2012 (const char *)iscsiboot_prop->boot_init.ini_name,
2013 ISCSI_MAX_NAME_LEN);
2014 } else {
2015 (void) snprintf((char *)ihp->hba_name,
2016 ISCSI_MAX_NAME_LEN,
2017 "iqn.1986-03.com.sun:01:");
2018
2019 (void) localetheraddr(NULL, &eaddr);
2020 for (i = 0; i < ETHERADDRL; i++) {
2021 (void) snprintf(val, sizeof (val), "%02x",
2022 eaddr.ether_addr_octet[i]);
2023 (void) strncat((char *)ihp->hba_name, val,
2024 ISCSI_MAX_NAME_LEN);
2025 }
2026
2027 /* Set default initiator-node alias */
2028 x = ddi_get_time();
2029 (void) snprintf(val, sizeof (val), ".%lx", x);
2030 (void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN);
2031
2032 if (ihp->hba_alias[0] == '\0') {
2033 (void) strncpy((char *)ihp->hba_alias,
2034 utsname.nodename, ISCSI_MAX_NAME_LEN);
2035 ihp->hba_alias_length = strlen((char *)ihp->hba_alias);
2036 if (minimal == B_FALSE) {
2037 (void) persistent_alias_name_set(
2038 (char *)ihp->hba_alias);
2039 }
2040 }
2041 }
2042
2043 if (minimal == B_TRUE) {
2044 return;
2045 }
2046
2047 (void) persistent_initiator_name_set((char *)ihp->hba_name);
2048
2049 /* Set default initiator-node CHAP settings */
2050 if (persistent_initiator_name_get((char *)ihp->hba_name,
2051 ISCSI_MAX_NAME_LEN) == B_TRUE) {
2052 chap = (iscsi_chap_props_t *)kmem_zalloc(sizeof (*chap),
2053 KM_SLEEP);
2054 if (persistent_chap_get((char *)ihp->hba_name, chap) ==
2055 B_FALSE) {
2056 bcopy((char *)ihp->hba_name, chap->c_user,
2057 strlen((char *)ihp->hba_name));
2058 chap->c_user_len = strlen((char *)ihp->hba_name);
2059 (void) persistent_chap_set((char *)ihp->hba_name, chap);
2060 }
2061 kmem_free(chap, sizeof (*chap));
2062 }
2063 }
2064
2065 static void
iscsid_remove_target_param(char * name)2066 iscsid_remove_target_param(char *name)
2067 {
2068 persistent_param_t *pparam;
2069 uint32_t t_oid;
2070 iscsi_config_sess_t *ics;
2071
2072 ASSERT(name != NULL);
2073
2074 /*
2075 * Remove target-param <-> target mapping.
2076 * Only remove if there is not any overridden
2077 * parameters in the persistent store
2078 */
2079 pparam = (persistent_param_t *)kmem_zalloc(sizeof (*pparam), KM_SLEEP);
2080
2081 /*
2082 * setup initial buffer for configured session
2083 * information
2084 */
2085 ics = (iscsi_config_sess_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
2086 ics->ics_in = 1;
2087
2088 if ((persistent_param_get(name, pparam) == B_FALSE) &&
2089 (persistent_get_config_session(name, ics) == B_FALSE)) {
2090 t_oid = iscsi_targetparam_get_oid((uchar_t *)name);
2091 (void) iscsi_targetparam_remove_target(t_oid);
2092 }
2093
2094 kmem_free(pparam, sizeof (*pparam));
2095 pparam = NULL;
2096 kmem_free(ics, sizeof (*ics));
2097 ics = NULL;
2098 }
2099
2100 /*
2101 * iscsid_addr_to_sockaddr - convert other types to struct sockaddr
2102 */
2103 void
iscsid_addr_to_sockaddr(int src_insize,void * src_addr,int src_port,struct sockaddr * dst_addr)2104 iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port,
2105 struct sockaddr *dst_addr)
2106 {
2107 ASSERT((src_insize == sizeof (struct in_addr)) ||
2108 (src_insize == sizeof (struct in6_addr)));
2109 ASSERT(src_addr != NULL);
2110 ASSERT(dst_addr != NULL);
2111
2112 bzero(dst_addr, sizeof (*dst_addr));
2113
2114 /* translate discovery information */
2115 if (src_insize == sizeof (struct in_addr)) {
2116 struct sockaddr_in *addr_in =
2117 (struct sockaddr_in *)dst_addr;
2118 addr_in->sin_family = AF_INET;
2119 bcopy(src_addr, &addr_in->sin_addr.s_addr,
2120 sizeof (struct in_addr));
2121 addr_in->sin_port = htons(src_port);
2122 } else {
2123 struct sockaddr_in6 *addr_in6 =
2124 (struct sockaddr_in6 *)dst_addr;
2125 addr_in6->sin6_family = AF_INET6;
2126 bcopy(src_addr, &addr_in6->sin6_addr.s6_addr,
2127 sizeof (struct in6_addr));
2128 addr_in6->sin6_port = htons(src_port);
2129 }
2130 }
2131
2132 /*
2133 * iscsi_discovery_event -- send event associated with discovery operations
2134 *
2135 * Each discovery event has a start and end event. Which is sent is based
2136 * on the boolean argument start with the obvious results.
2137 */
2138 static void
iscsi_discovery_event(iscsi_hba_t * ihp,iSCSIDiscoveryMethod_t m,boolean_t start)2139 iscsi_discovery_event(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t m,
2140 boolean_t start)
2141 {
2142 char *subclass = NULL;
2143
2144 mutex_enter(&ihp->hba_discovery_events_mutex);
2145 switch (m) {
2146 case iSCSIDiscoveryMethodStatic:
2147 if (start == B_TRUE) {
2148 subclass = ESC_ISCSI_STATIC_START;
2149 } else {
2150 ihp->hba_discovery_events |= iSCSIDiscoveryMethodStatic;
2151 subclass = ESC_ISCSI_STATIC_END;
2152 }
2153 break;
2154
2155 case iSCSIDiscoveryMethodSendTargets:
2156 if (start == B_TRUE) {
2157 subclass = ESC_ISCSI_SEND_TARGETS_START;
2158 } else {
2159 ihp->hba_discovery_events |=
2160 iSCSIDiscoveryMethodSendTargets;
2161 subclass = ESC_ISCSI_SEND_TARGETS_END;
2162 }
2163 break;
2164
2165 case iSCSIDiscoveryMethodSLP:
2166 if (start == B_TRUE) {
2167 subclass = ESC_ISCSI_SLP_START;
2168 } else {
2169 ihp->hba_discovery_events |= iSCSIDiscoveryMethodSLP;
2170 subclass = ESC_ISCSI_SLP_END;
2171 }
2172 break;
2173
2174 case iSCSIDiscoveryMethodISNS:
2175 if (start == B_TRUE) {
2176 subclass = ESC_ISCSI_ISNS_START;
2177 } else {
2178 ihp->hba_discovery_events |= iSCSIDiscoveryMethodISNS;
2179 subclass = ESC_ISCSI_ISNS_END;
2180 }
2181 break;
2182 }
2183 mutex_exit(&ihp->hba_discovery_events_mutex);
2184 iscsi_send_sysevent(ihp, EC_ISCSI, subclass, NULL);
2185 }
2186
2187 /*
2188 * iscsi_send_sysevent -- send sysevent using specified class
2189 */
2190 void
iscsi_send_sysevent(iscsi_hba_t * ihp,char * eventclass,char * subclass,nvlist_t * np)2191 iscsi_send_sysevent(
2192 iscsi_hba_t *ihp,
2193 char *eventclass,
2194 char *subclass,
2195 nvlist_t *np)
2196 {
2197 (void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, eventclass,
2198 subclass, np, NULL, DDI_SLEEP);
2199 }
2200
2201 static boolean_t
iscsid_boot_init_config(iscsi_hba_t * ihp)2202 iscsid_boot_init_config(iscsi_hba_t *ihp)
2203 {
2204 if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) {
2205 bcopy(iscsiboot_prop->boot_init.ini_name,
2206 ihp->hba_name,
2207 strlen((const char *)iscsiboot_prop->boot_init.ini_name));
2208 }
2209 /* or using default login param for boot session */
2210 return (B_TRUE);
2211 }
2212
2213 boolean_t
iscsi_reconfig_boot_sess(iscsi_hba_t * ihp)2214 iscsi_reconfig_boot_sess(iscsi_hba_t *ihp)
2215 {
2216 iscsi_config_sess_t *ics;
2217 int idx;
2218 iscsi_sess_t *isp, *t_isp;
2219 int isid, size;
2220 char *name;
2221 boolean_t rtn = B_TRUE;
2222 uint32_t event_count;
2223
2224 if (iscsiboot_prop == NULL) {
2225 return (B_FALSE);
2226 }
2227 size = sizeof (*ics);
2228 ics = kmem_zalloc(size, KM_SLEEP);
2229 ics->ics_in = 1;
2230
2231 /* get information of number of sessions to be configured */
2232 name = (char *)iscsiboot_prop->boot_tgt.tgt_name;
2233 if (persistent_get_config_session(name, ics) == B_FALSE) {
2234 /*
2235 * No target information available to check
2236 * initiator information. Assume one session
2237 * by default.
2238 */
2239 name = (char *)iscsiboot_prop->boot_init.ini_name;
2240 if (persistent_get_config_session(name, ics) == B_FALSE) {
2241 ics->ics_out = 1;
2242 ics->ics_bound = B_TRUE;
2243 }
2244 }
2245
2246 /* get necessary information */
2247 if (ics->ics_out > 1) {
2248 idx = ics->ics_out;
2249 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
2250 kmem_free(ics, sizeof (*ics));
2251
2252 ics = kmem_zalloc(size, KM_SLEEP);
2253 ics->ics_in = idx;
2254
2255 /* get configured sessions information */
2256 if (persistent_get_config_session((char *)name,
2257 ics) != B_TRUE) {
2258 cmn_err(CE_NOTE, "session(%s) - "
2259 "failed to setup multiple sessions",
2260 name);
2261 kmem_free(ics, size);
2262 return (B_FALSE);
2263 }
2264 }
2265
2266 /* create a temporary session to keep boot session connective */
2267 t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS);
2268 if (t_isp == NULL) {
2269 cmn_err(CE_NOTE, "session(%s) - "
2270 "failed to setup multiple sessions", name);
2271 rw_exit(&ihp->hba_sess_list_rwlock);
2272 kmem_free(ics, size);
2273 return (B_FALSE);
2274 }
2275
2276 /* destroy all old boot sessions */
2277 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2278 isp = ihp->hba_sess_list;
2279 while (isp != NULL) {
2280 if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
2281 if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) {
2282 /*
2283 * destroy all stale sessions
2284 * except temporary boot session
2285 */
2286 if (ISCSI_SUCCESS(iscsi_sess_destroy(
2287 isp))) {
2288 isp = ihp->hba_sess_list;
2289 } else {
2290 /*
2291 * couldn't destroy stale sessions
2292 * at least poke it to disconnect
2293 */
2294 event_count = atomic_inc_32_nv(
2295 &isp->sess_state_event_count);
2296 iscsi_sess_enter_state_zone(isp);
2297 iscsi_sess_state_machine(isp,
2298 ISCSI_SESS_EVENT_N7, event_count);
2299 iscsi_sess_exit_state_zone(isp);
2300
2301 isp = isp->sess_next;
2302 cmn_err(CE_NOTE, "session(%s) - "
2303 "failed to setup multiple"
2304 " sessions", name);
2305 }
2306 } else {
2307 isp = isp->sess_next;
2308 }
2309 } else {
2310 isp = isp->sess_next;
2311 }
2312 }
2313 rw_exit(&ihp->hba_sess_list_rwlock);
2314
2315 for (isid = 0; isid < ics->ics_out; isid++) {
2316 isp = iscsi_add_boot_sess(ihp, isid);
2317 if (isp == NULL) {
2318 cmn_err(CE_NOTE, "session(%s) - failed to setup"
2319 " multiple sessions", name);
2320 rtn = B_FALSE;
2321 break;
2322 }
2323 }
2324 if (!rtn && (isid == 0)) {
2325 /*
2326 * fail to create any new boot session
2327 * so only the temporary session is alive
2328 * quit without destroying it
2329 */
2330 kmem_free(ics, size);
2331 return (rtn);
2332 }
2333
2334 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2335 if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) {
2336 /* couldn't destroy temp boot session */
2337 cmn_err(CE_NOTE, "session(%s) - "
2338 "failed to setup multiple sessions", name);
2339 rw_exit(&ihp->hba_sess_list_rwlock);
2340 rtn = B_FALSE;
2341 }
2342 rw_exit(&ihp->hba_sess_list_rwlock);
2343
2344 kmem_free(ics, size);
2345 return (rtn);
2346 }
2347
2348 static iscsi_sess_t *
iscsi_add_boot_sess(iscsi_hba_t * ihp,int isid)2349 iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid)
2350 {
2351 iscsi_sess_t *isp;
2352 iscsi_conn_t *icp;
2353 uint_t oid;
2354
2355 iscsi_sockaddr_t addr_dst;
2356
2357 addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family;
2358 if (addr_dst.sin.sa_family == AF_INET) {
2359 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr,
2360 &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr));
2361 addr_dst.sin4.sin_port =
2362 htons(iscsiboot_prop->boot_tgt.tgt_port);
2363 } else {
2364 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr,
2365 &addr_dst.sin6.sin6_addr.s6_addr,
2366 sizeof (struct in6_addr));
2367 addr_dst.sin6.sin6_port =
2368 htons(iscsiboot_prop->boot_tgt.tgt_port);
2369 }
2370
2371 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2372 isp = iscsi_sess_create(ihp,
2373 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
2374 (struct sockaddr *)&addr_dst,
2375 (char *)iscsiboot_prop->boot_tgt.tgt_name,
2376 ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
2377 if (isp == NULL) {
2378 /* create temp booting session failed */
2379 rw_exit(&ihp->hba_sess_list_rwlock);
2380 return (NULL);
2381 }
2382 isp->sess_boot = B_TRUE;
2383
2384 if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst,
2385 isp, &icp))) {
2386 rw_exit(&ihp->hba_sess_list_rwlock);
2387 return (NULL);
2388 }
2389
2390 rw_exit(&ihp->hba_sess_list_rwlock);
2391 /* now online created session */
2392 if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name,
2393 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
2394 (struct sockaddr *)&addr_dst) == B_FALSE) {
2395 return (NULL);
2396 }
2397
2398 return (isp);
2399 }
2400
2401 static void
iscsid_thread_boot_wd(iscsi_thread_t * thread,void * p)2402 iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p)
2403 {
2404 int rc = 1;
2405 iscsi_hba_t *ihp = (iscsi_hba_t *)p;
2406 boolean_t reconfigured = B_FALSE;
2407
2408 while (rc != 0) {
2409 if (iscsiboot_prop && (modrootloaded == 1)) {
2410 if (ihp->hba_persistent_loaded == B_FALSE) {
2411 if (persistent_load() == B_TRUE) {
2412 ihp->hba_persistent_loaded = B_TRUE;
2413 }
2414 }
2415 if ((ihp->hba_persistent_loaded == B_TRUE) &&
2416 (reconfigured == B_FALSE)) {
2417 if (iscsi_chk_bootlun_mpxio(ihp) == B_TRUE) {
2418 (void) iscsi_reconfig_boot_sess(ihp);
2419 iscsid_poke_discovery(ihp,
2420 iSCSIDiscoveryMethodUnknown);
2421 (void) iscsid_login_tgt(ihp, NULL,
2422 iSCSIDiscoveryMethodUnknown, NULL);
2423 }
2424 reconfigured = B_TRUE;
2425 }
2426 break;
2427 }
2428 rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
2429 }
2430 }
2431
2432 boolean_t
iscsi_cmp_boot_tgt_name(char * name)2433 iscsi_cmp_boot_tgt_name(char *name)
2434 {
2435 if (iscsiboot_prop && (strncmp((const char *)name,
2436 (const char *)iscsiboot_prop->boot_tgt.tgt_name,
2437 ISCSI_MAX_NAME_LEN) == 0)) {
2438 return (B_TRUE);
2439 } else {
2440 return (B_FALSE);
2441 }
2442 }
2443
2444 boolean_t
iscsi_cmp_boot_ini_name(char * name)2445 iscsi_cmp_boot_ini_name(char *name)
2446 {
2447 if (iscsiboot_prop && (strncmp((const char *)name,
2448 (const char *)iscsiboot_prop->boot_init.ini_name,
2449 ISCSI_MAX_NAME_LEN) == 0)) {
2450 return (B_TRUE);
2451 } else {
2452 return (B_FALSE);
2453 }
2454 }
2455
2456 boolean_t
iscsi_chk_bootlun_mpxio(iscsi_hba_t * ihp)2457 iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp)
2458 {
2459 iscsi_sess_t *isp;
2460 iscsi_lun_t *ilp;
2461 isp = ihp->hba_sess_list;
2462 boolean_t tgt_mpxio_enabled = B_FALSE;
2463 boolean_t bootlun_found = B_FALSE;
2464 uint16_t lun_num;
2465
2466 if (iscsiboot_prop == NULL) {
2467 return (B_FALSE);
2468 }
2469
2470 if (!ihp->hba_mpxio_enabled) {
2471 return (B_FALSE);
2472 }
2473
2474 lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun));
2475
2476 while (isp != NULL) {
2477 if ((strncmp((char *)isp->sess_name,
2478 (const char *)iscsiboot_prop->boot_tgt.tgt_name,
2479 ISCSI_MAX_NAME_LEN) == 0) &&
2480 (isp->sess_boot == B_TRUE)) {
2481 /*
2482 * found boot session.
2483 * check its mdi path info is null or not
2484 */
2485 ilp = isp->sess_lun_list;
2486 while (ilp != NULL) {
2487 if (lun_num == ilp->lun_num) {
2488 if (ilp->lun_pip) {
2489 tgt_mpxio_enabled = B_TRUE;
2490 }
2491 bootlun_found = B_TRUE;
2492 }
2493 ilp = ilp->lun_next;
2494 }
2495 }
2496 isp = isp->sess_next;
2497 }
2498 if (bootlun_found) {
2499 return (tgt_mpxio_enabled);
2500 } else {
2501 /*
2502 * iscsiboot_prop not NULL while no boot lun found
2503 * in most cases this is none iscsi boot while iscsiboot_prop
2504 * is not NULL, in this scenario return iscsi HBA's mpxio config
2505 */
2506 return (ihp->hba_mpxio_enabled);
2507 }
2508 }
2509
2510 static boolean_t
iscsid_check_active_boot_conn(iscsi_hba_t * ihp)2511 iscsid_check_active_boot_conn(iscsi_hba_t *ihp)
2512 {
2513 iscsi_sess_t *isp = NULL;
2514 iscsi_conn_t *icp = NULL;
2515
2516 rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
2517 isp = ihp->hba_sess_list;
2518 while (isp != NULL) {
2519 if (isp->sess_boot == B_TRUE) {
2520 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2521 icp = isp->sess_conn_list;
2522 while (icp != NULL) {
2523 if (icp->conn_state ==
2524 ISCSI_CONN_STATE_LOGGED_IN) {
2525 rw_exit(&isp->sess_conn_list_rwlock);
2526 rw_exit(&ihp->hba_sess_list_rwlock);
2527 return (B_TRUE);
2528 }
2529 icp = icp->conn_next;
2530 }
2531 rw_exit(&isp->sess_conn_list_rwlock);
2532 }
2533 isp = isp->sess_next;
2534 }
2535 rw_exit(&ihp->hba_sess_list_rwlock);
2536
2537 return (B_FALSE);
2538 }
2539