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 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "isns_server.h"
33 #include "isns_msgq.h"
34 #include "isns_cache.h"
35 #include "isns_cfg.h"
36 #include "isns_obj.h"
37 #include "isns_dseng.h"
38 #include "isns_log.h"
39 #include "isns_scn.h"
40 #include "isns_pdu.h"
41
42 /*
43 * global variables.
44 */
45
46 /*
47 * local variables.
48 */
49 static scn_registry_t *scn_registry = NULL;
50 static int scn_dispatched = 0;
51
52 /*
53 * external variables.
54 */
55 extern uint8_t mgmt_scn;
56 extern msg_queue_t *sys_q;
57 extern msg_queue_t *scn_q;
58 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
59
60 #ifdef DEBUG
61 extern void dump_pdu1(isns_pdu_t *);
62 #endif
63
64 static int sf_gen(scn_raw_t *);
65 static int sf_error(scn_raw_t *);
66
67 static scn_raw_t *make_raw_entity(isns_obj_t *);
68 static scn_raw_t *make_raw_iscsi(isns_obj_t *);
69 static scn_raw_t *make_raw_portal(isns_obj_t *);
70 static scn_raw_t *make_raw_assoc_iscsi(isns_obj_t *);
71 static scn_raw_t *make_raw_assoc_dd(isns_obj_t *);
72 static scn_raw_t *(*const make_raw[MAX_OBJ_TYPE_FOR_SIZE])(isns_obj_t *) = {
73 NULL,
74 &make_raw_entity,
75 &make_raw_iscsi,
76 &make_raw_portal,
77 NULL, /* OBJ_PG */
78 NULL, /* OBJ_DD */
79 NULL, /* OBJ_DDS */
80 NULL, /* MAX_OBJ_TYPE */
81 NULL, /* OBJ_DUMMY1 */
82 NULL, /* OBJ_DUMMY2 */
83 NULL, /* OBJ_DUMMY3 */
84 NULL, /* OBJ_DUMMY4 */
85 &make_raw_assoc_iscsi,
86 &make_raw_assoc_dd
87 };
88
89 static scn_text_t *scn_gen_entity(scn_raw_t *);
90 static scn_text_t *scn_gen_iscsi(scn_raw_t *);
91 static scn_text_t *scn_gen_portal(scn_raw_t *);
92 static scn_text_t *scn_gen_assoc_dd(scn_raw_t *);
93 static scn_text_t *(*const scn_gen[MAX_OBJ_TYPE_FOR_SIZE])(scn_raw_t *) = {
94 NULL,
95 &scn_gen_entity,
96 &scn_gen_iscsi,
97 &scn_gen_portal,
98 NULL, /* OBJ_PG */
99 NULL, /* OBJ_DD */
100 NULL, /* OBJ_DDS */
101 NULL, /* MAX_OBJ_TYPE */
102 NULL, /* OBJ_DUMMY1 */
103 NULL, /* OBJ_DUMMY2 */
104 NULL, /* OBJ_DUMMY3 */
105 NULL, /* OBJ_DUMMY4 */
106 &scn_gen_iscsi,
107 &scn_gen_assoc_dd
108 };
109
110 #define SCN_TEST(E, BITMAP, UID1, UID2, NT) \
111 (((E) & (BITMAP)) && \
112 (!((BITMAP) & (ISNS_INIT_SELF_INFO_ONLY | \
113 ISNS_TARGET_SELF_INFO_ONLY)) || \
114 ((UID1) == (UID2)) || \
115 (((BITMAP) & ISNS_INIT_SELF_INFO_ONLY) && \
116 ((NT) & ISNS_INITIATOR_NODE_TYPE)) || \
117 (((BITMAP) & ISNS_TARGET_SELF_INFO_ONLY) && \
118 ((NT) & ISNS_TARGET_NODE_TYPE))))
119
120 /*
121 * local functions.
122 */
123
124 /*
125 * ****************************************************************************
126 *
127 * free_portal_1:
128 * Free one SCN portal or decrease the reference count if the portal
129 * is referenced by other SCN entry(s).
130 *
131 * p - the portal.
132 *
133 * ****************************************************************************
134 */
135 static void
free_portal_1(scn_portal_t * p)136 free_portal_1(
137 scn_portal_t *p
138 )
139 {
140 if (p->ref <= 1) {
141 if (p->sz == sizeof (in6_addr_t)) {
142 free(p->ip.in6);
143 }
144 free(p);
145 } else {
146 p->ref --;
147 }
148 }
149
150 /*
151 * ****************************************************************************
152 *
153 * free_portal:
154 * Free the unused portals, which are extracted for new SCN entry,
155 * after the new SCN entry is added.
156 *
157 * p - the portal.
158 *
159 * ****************************************************************************
160 */
161 static void
free_portal(scn_portal_t * p)162 free_portal(
163 scn_portal_t *p
164 )
165 {
166 scn_portal_t *n;
167
168 while (p != NULL) {
169 n = p->next;
170 free_portal_1(p);
171 p = n;
172 }
173 }
174
175 /*
176 * ****************************************************************************
177 *
178 * free_portal_list:
179 * Free the list of portals while a SCN entry is being destroyed.
180 *
181 * l - the portal list.
182 *
183 * ****************************************************************************
184 */
185 static void
free_portal_list(scn_list_t * l)186 free_portal_list(
187 scn_list_t *l
188 )
189 {
190 scn_list_t *n;
191 scn_portal_t *p;
192
193 while (l != NULL) {
194 n = l->next;
195 p = l->data.portal;
196 free_portal_1(p);
197 free(l);
198 l = n;
199 }
200 }
201
202 /*
203 * ****************************************************************************
204 *
205 * free_scn_text:
206 * Free one SCN or decrease the ref count after the SCN is emitted.
207 *
208 * text - the SCN.
209 *
210 * ****************************************************************************
211 */
212 static void
free_scn_text(scn_text_t * text)213 free_scn_text(
214 scn_text_t *text
215 )
216 {
217 if (text->ref <= 1) {
218 free(text->iscsi);
219 free(text);
220 } else {
221 text->ref --;
222 }
223 }
224
225 /*
226 * ****************************************************************************
227 *
228 * free_scn_list:
229 * Free the the list of SCN.
230 *
231 * scn - the list.
232 *
233 * ****************************************************************************
234 */
235 static void
free_scn_list(scn_t * scn)236 free_scn_list(
237 scn_t *scn
238 )
239 {
240 scn_t *next_scn;
241 scn_list_t *list;
242 scn_list_t *next_list;
243
244 while (scn != NULL) {
245 next_scn = scn->next;
246 list = scn->data.list;
247 while (list != NULL) {
248 next_list = list->next;
249 free_scn_text(list->data.text);
250 free(list);
251 list = next_list;
252 }
253 free(scn);
254 scn = next_scn;
255 }
256 }
257
258 /*
259 * ****************************************************************************
260 *
261 * free_scn:
262 * Free all of SCNs which are dispatched to every entry.
263 *
264 * ****************************************************************************
265 */
266 static void
free_scn()267 free_scn(
268 )
269 {
270 scn_registry_t *p;
271
272 p = scn_registry;
273
274 while (p != NULL) {
275 free_scn_list(p->scn);
276 p->scn = NULL;
277 p = p->next;
278 }
279 }
280
281 /*
282 * ****************************************************************************
283 *
284 * free_entry:
285 * Free one SCN entry.
286 *
287 * e - the SCN entry.
288 *
289 * ****************************************************************************
290 */
291 static void
free_entry(scn_registry_t * e)292 free_entry(
293 scn_registry_t *e
294 )
295 {
296 free_scn_list(e->scn);
297 free_portal_list(e->portal.l);
298 free(e->name);
299 free(e);
300 }
301
302 /*
303 * ****************************************************************************
304 *
305 * free_raw:
306 * Free the raw data after the SCN is generated from it.
307 *
308 * raw - the raw SCN data.
309 *
310 * ****************************************************************************
311 */
312 static void
free_raw(scn_raw_t * raw)313 free_raw(
314 scn_raw_t *raw
315 )
316 {
317 if (raw->ref == 0) {
318 free(raw->iscsi);
319 }
320 if (raw->ip != NULL) {
321 free(raw->ip);
322 }
323 free(raw);
324 }
325
326 /*
327 * ****************************************************************************
328 *
329 * scn_add_portal:
330 * Add portals to the portal list of a SCN entry.
331 *
332 * e - the SCN entry.
333 * p - the portals.
334 * return - 0: successful, otherwise failed.
335 *
336 * ****************************************************************************
337 */
338 static int
scn_add_portal(scn_registry_t * e,scn_portal_t * p)339 scn_add_portal(
340 scn_registry_t *e,
341 scn_portal_t *p
342 )
343 {
344 scn_portal_t *x;
345 scn_list_t *l, *m;
346
347 scn_list_t **lp;
348
349 int found_it;
350
351 lp = &e->portal.l;
352 while (p != NULL) {
353 m = (scn_list_t *)malloc(sizeof (scn_list_t));
354 if (m == NULL) {
355 return (1);
356 }
357 found_it = 0;
358 e = scn_registry;
359 while (e && !found_it) {
360 l = e->portal.l;
361 while (l && !found_it) {
362 x = l->data.portal;
363 if (x->uid == p->uid) {
364 found_it = 1;
365 }
366 l = l->next;
367 }
368 e = e->next;
369 }
370
371 if (!found_it) {
372 x = p;
373 }
374 m->data.portal = x;
375 x->ref ++;
376 m->next = *lp;
377 *lp = m;
378
379 p = p->next;
380 }
381
382 return (0);
383 }
384
385 /*
386 * ****************************************************************************
387 *
388 * scn_remove_portal:
389 * Remove a portal from the portal list of every SCN entry.
390 *
391 * uid - the portal object uid.
392 * return - always successful (0).
393 *
394 * ****************************************************************************
395 */
396 static int
scn_remove_portal(uint32_t uid)397 scn_remove_portal(
398 uint32_t uid
399 )
400 {
401 scn_registry_t **ep, *e;
402
403 scn_portal_t *x;
404 scn_list_t **lp, *l;
405
406 ep = &scn_registry;
407 e = *ep;
408
409 while (e != NULL) {
410 lp = &e->portal.l;
411 l = *lp;
412 while (l != NULL) {
413 x = l->data.portal;
414 if (x->uid == uid) {
415 /* remove it */
416 *lp = l->next;
417 free_portal_1(x);
418 free(l);
419 } else {
420 lp = &l->next;
421 }
422 l = *lp;
423 }
424
425 if (e->portal.l == NULL) {
426 /* no portal for this entry, destroy it */
427 *ep = e->next;
428 free_entry(e);
429 } else {
430 ep = &e->next;
431 }
432 e = *ep;
433 }
434
435 return (0);
436 }
437
438 /*
439 * ****************************************************************************
440 *
441 * scn_list_add:
442 * Add one SCN entry to the SCN entry list.
443 *
444 * e - the SCN entry.
445 * return - always successful (0).
446 *
447 * ****************************************************************************
448 */
449 static int
scn_list_add(scn_registry_t * e)450 scn_list_add(
451 scn_registry_t *e
452 )
453 {
454 scn_registry_t **pp;
455 scn_portal_t *p;
456
457 p = e->portal.p;
458 e->portal.l = NULL;
459
460 pp = &scn_registry;
461 while (*pp) {
462 if ((*pp)->uid == e->uid) {
463 /* replace the bitmap */
464 (*pp)->bitmap = e->bitmap;
465 free_portal(p);
466 free_entry(e);
467 return (0);
468 } else if ((*pp)->uid < e->uid) {
469 break;
470 }
471 pp = &(*pp)->next;
472 }
473
474 (void) scn_add_portal(e, p);
475
476 if (e->portal.l != NULL || sys_q == NULL) {
477 /* insert it to the list */
478 e->next = *pp;
479 *pp = e;
480 } else {
481 /* no portal, ignore it */
482 free_entry(e);
483 }
484
485 /* free the unused portal(s) */
486 free_portal(p);
487
488 return (0);
489 }
490
491 /*
492 * ****************************************************************************
493 *
494 * scn_list_remove:
495 * Remove one SCN entry from the SCN entry list.
496 *
497 * uid - the SCN entry unique ID.
498 * return - always successful (0).
499 *
500 * ****************************************************************************
501 */
502 static int
scn_list_remove(uint32_t uid)503 scn_list_remove(
504 uint32_t uid
505 )
506 {
507 scn_registry_t **ep, *e;
508
509 ep = &scn_registry;
510 e = *ep;
511 while (e) {
512 if (e->uid == uid) {
513 /* destroy it */
514 *ep = e->next;
515 free_entry(e);
516 break;
517 } else if (e->uid < uid) {
518 break;
519 }
520 ep = &e->next;
521 e = *ep;
522 }
523
524 return (0);
525 }
526
527 /*
528 * ****************************************************************************
529 *
530 * cb_get_scn_port:
531 * The callback function which returns the SCN port of a portal object.
532 *
533 * p1 - the portal object.
534 * p2 - the lookup control data.
535 * return - the SCN port number.
536 *
537 * ****************************************************************************
538 */
539 static int
cb_get_scn_port(void * p1,void * p2)540 cb_get_scn_port(
541 void *p1,
542 /*ARGSUSED*/
543 void *p2
544 )
545 {
546 isns_obj_t *obj = (isns_obj_t *)p1;
547
548 isns_attr_t *attr = &obj->attrs[
549 ATTR_INDEX_PORTAL(ISNS_SCN_PORT_ATTR_ID)];
550
551 int port = 0;
552
553 if (attr->tag != 0 && attr->value.ui != 0) {
554 port = (int)attr->value.ui;
555 }
556
557 return (port);
558 }
559
560 /*
561 * ****************************************************************************
562 *
563 * new_scn_portal:
564 * Make a new SCN portal.
565 *
566 * ref - the ref count.
567 * uid - the portal object UID.
568 * ip - the ip address.
569 * port - the port number.
570 * return - the SCN portal.
571 *
572 * ****************************************************************************
573 */
574 static scn_portal_t *
new_scn_portal(uint32_t ref,uint32_t uid,in6_addr_t * ip,uint32_t port)575 new_scn_portal(
576 uint32_t ref,
577 uint32_t uid,
578 in6_addr_t *ip,
579 uint32_t port
580 )
581 {
582 scn_portal_t *p;
583
584 p = (scn_portal_t *)malloc(sizeof (scn_portal_t));
585 if (p != NULL) {
586 p->uid = uid;
587 /* convert the ipv6 to ipv4 */
588 if (((int *)ip)[0] == 0x00 &&
589 ((int *)ip)[1] == 0x00 &&
590 ((uchar_t *)ip)[8] == 0x00 &&
591 ((uchar_t *)ip)[9] == 0x00 &&
592 ((uchar_t *)ip)[10] == 0xFF &&
593 ((uchar_t *)ip)[11] == 0xFF) {
594 p->sz = sizeof (in_addr_t);
595 p->ip.in = ((uint32_t *)ip)[3];
596 free(ip);
597 } else {
598 p->sz = sizeof (in6_addr_t);
599 p->ip.in6 = ip;
600 }
601 p->port = port;
602 p->ref = ref;
603 p->so = 0;
604 p->next = NULL;
605 }
606
607 return (p);
608 }
609
610 /*
611 * ****************************************************************************
612 *
613 * extract scn_portal:
614 * Extract the SCN portal(s) for a storage node.
615 *
616 * name - the storage node name.
617 * return - the SCN portal list.
618 *
619 * ****************************************************************************
620 */
621 static scn_portal_t *
extract_scn_portal(uchar_t * name)622 extract_scn_portal(
623 uchar_t *name
624 )
625 {
626 scn_portal_t *list = NULL;
627 scn_portal_t *p;
628
629 lookup_ctrl_t lc_pg, lc_p;
630 uint32_t pg_uid, uid;
631
632 in6_addr_t *ip;
633 uint32_t port;
634
635 lc_pg.type = OBJ_PG;
636 lc_pg.curr_uid = 0;
637 lc_pg.id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID);
638 lc_pg.op[0] = OP_STRING;
639 lc_pg.data[0].ptr = name;
640 lc_pg.op[1] = 0;
641
642 lc_pg.id[1] = ISNS_PG_PORTAL_IP_ADDR_ATTR_ID;
643 lc_pg.id[2] = ISNS_PG_PORTAL_PORT_ATTR_ID;
644
645 lc_p.type = OBJ_PORTAL;
646 lc_p.curr_uid = 0;
647 lc_p.id[0] = ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID);
648 lc_p.op[0] = OP_MEMORY_IP6;
649 lc_p.id[1] = ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID);
650 lc_p.op[1] = OP_INTEGER;
651 lc_p.op[2] = 0;
652
653 while (cache_lookup(&lc_pg, &pg_uid, cb_clone_attrs) == 0 &&
654 pg_uid != 0) {
655 ip = lc_pg.data[1].ip;
656 port = lc_pg.data[2].ui;
657 if (ip != NULL) {
658 lc_p.data[0].ip = ip;
659 lc_p.data[1].ui = port;
660 port = cache_lookup(&lc_p, &uid, cb_get_scn_port);
661 if (port != 0 && uid != 0) {
662 /* ref starts from 1 */
663 p = new_scn_portal(1, uid, ip, port);
664 if (p != NULL) {
665 p->next = list;
666 list = p;
667 } else {
668 free(ip);
669 free(p);
670 }
671 } else {
672 /* portal not registered or no scn port */
673 free(ip);
674 }
675 }
676 lc_pg.curr_uid = pg_uid;
677 }
678
679 return (list);
680 }
681
682 /*
683 * ****************************************************************************
684 *
685 * cb_update_scn_bitmap:
686 * The callback function which updates the SCN Bitmap attribute of
687 * a storage node object.
688 *
689 * p1 - the storage node object.
690 * p2 - the lookup control data.
691 * return - error code.
692 *
693 * ****************************************************************************
694 */
695 static int
cb_update_scn_bitmap(void * p1,void * p2)696 cb_update_scn_bitmap(
697 void *p1,
698 void *p2
699 )
700 {
701 int ec = 0;
702
703 isns_obj_t *obj = (isns_obj_t *)p1;
704 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
705
706 int id = ATTR_INDEX_ISCSI(ISNS_ISCSI_SCN_BITMAP_ATTR_ID);
707 isns_attr_t *attr = &obj->attrs[id];
708
709 uint32_t bitmap = lcp->data[2].ui;
710
711 if (bitmap != 0) {
712 attr->tag = ISNS_ISCSI_SCN_BITMAP_ATTR_ID;
713 attr->len = 4;
714 } else if (attr->tag == 0) {
715 return (ec);
716 } else {
717 attr->tag = 0;
718 attr->len = 0;
719 }
720 attr->value.ui = bitmap;
721
722 if (sys_q != NULL) {
723 ec = write_data(DATA_UPDATE, obj);
724 }
725
726 return (ec);
727 }
728
729 /*
730 * ****************************************************************************
731 *
732 * cb_get_node_type:
733 * The callback function which returns the node type attribute of
734 * a storage node object.
735 *
736 * p1 - the storage node object.
737 * p2 - the lookup control data.
738 * return - error code.
739 *
740 * ****************************************************************************
741 */
742 static int
cb_get_node_type(void * p1,void * p2)743 cb_get_node_type(
744 void *p1,
745 /* LINTED E_FUNC_ARG_UNUSED */
746 void *p2
747 )
748 {
749 isns_obj_t *obj = (isns_obj_t *)p1;
750 isns_attr_t *attr = &obj->attrs[
751 ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
752 int nt = (int)attr->value.ui;
753
754 return (nt);
755 }
756
757 /*
758 * ****************************************************************************
759 *
760 * cb_get_node_type:
761 * The callback function which returns the storage node object UID
762 * from a portal group object.
763 *
764 * p1 - the pg object.
765 * p2 - the lookup control data.
766 * return - the storage node object UID.
767 *
768 * ****************************************************************************
769 */
770 static int
cb_pg_node(void * p1,void * p2)771 cb_pg_node(
772 void *p1,
773 /* LINTED E_FUNC_ARG_UNUSED */
774 void *p2
775 )
776 {
777 uint32_t ref;
778
779 ref = get_ref_t(p1, OBJ_ISCSI);
780
781 return ((int)ref);
782 }
783
784 /*
785 * ****************************************************************************
786 *
787 * make_raw_entity:
788 * Make raw SCN data with a Network Entity object.
789 *
790 * obj - the network entity object.
791 * return - the raw SCN data.
792 *
793 * ****************************************************************************
794 */
795 static scn_raw_t *
make_raw_entity(isns_obj_t * obj)796 make_raw_entity(
797 /*ARGSUSED*/
798 isns_obj_t *obj
799 )
800 {
801 scn_raw_t *raw;
802
803 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
804 if (raw != NULL) {
805 raw->type = obj->type;
806 raw->uid = get_obj_uid(obj);
807 raw->iscsi = NULL;
808 raw->ref = 0;
809 raw->ilen = 0;
810 raw->nt = 0;
811 raw->ip = NULL;
812 raw->dd_id = 0;
813 raw->dds_id = 0;
814 } else {
815 isnslog(LOG_DEBUG, "make_raw_entity", "malloc failed.");
816 }
817
818 return (raw);
819 }
820
821 /*
822 * ****************************************************************************
823 *
824 * make_raw_iscsi:
825 * Make raw SCN data with a Storage Node object.
826 *
827 * obj - the storage node object.
828 * return - the raw SCN data.
829 *
830 * ****************************************************************************
831 */
832 static scn_raw_t *
make_raw_iscsi(isns_obj_t * obj)833 make_raw_iscsi(
834 isns_obj_t *obj
835 )
836 {
837 uint32_t uid;
838 uint32_t nt;
839 uchar_t *iscsi;
840 uint32_t ilen;
841
842 isns_attr_t *attr;
843
844 scn_raw_t *raw;
845
846 uid = get_obj_uid(obj);
847 attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
848 nt = attr->value.ui;
849 attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
850
851 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
852 ilen = attr->len;
853 iscsi = (uchar_t *)malloc(ilen);
854 if (raw != NULL && iscsi != NULL) {
855 /* copy the iscsi storage node name */
856 (void) strcpy((char *)iscsi, (char *)attr->value.ptr);
857
858 raw->type = obj->type;
859 raw->uid = uid;
860 raw->iscsi = iscsi;
861 raw->ref = 0;
862 raw->ilen = ilen;
863 raw->nt = nt;
864 raw->ip = NULL;
865 raw->dd_id = 0;
866 raw->dds_id = 0;
867 } else {
868 free(raw);
869 free(iscsi);
870 raw = NULL;
871 isnslog(LOG_DEBUG, "make_raw_iscsi", "malloc failed.");
872 }
873
874 return (raw);
875 }
876
877 /*
878 * ****************************************************************************
879 *
880 * make_raw_portal:
881 * Make raw SCN data with a Portal object.
882 *
883 * obj - the portal object.
884 * return - the raw SCN data.
885 *
886 * ****************************************************************************
887 */
888 static scn_raw_t *
make_raw_portal(isns_obj_t * obj)889 make_raw_portal(
890 isns_obj_t *obj
891 )
892 {
893 isns_attr_t *attr;
894 in6_addr_t *ip;
895 uint32_t port;
896
897 scn_raw_t *raw;
898
899 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
900 ip = (in6_addr_t *)malloc(sizeof (in6_addr_t));
901 if (raw != NULL && ip != NULL) {
902 attr = &obj->attrs[
903 ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)];
904 (void) memcpy(ip, attr->value.ip, sizeof (in6_addr_t));
905 attr = &obj->attrs[
906 ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)];
907 port = attr->value.ui;
908
909 raw->type = obj->type;
910 raw->uid = 0;
911 raw->iscsi = NULL;
912 raw->ref = 0;
913 raw->ilen = 0;
914 raw->nt = 0;
915 raw->ip = ip;
916 raw->port = port;
917 raw->dd_id = 0;
918 raw->dds_id = 0;
919 } else {
920 free(ip);
921 free(raw);
922 raw = NULL;
923 isnslog(LOG_DEBUG, "make_raw_portal", "malloc failed.");
924 }
925
926 return (raw);
927 }
928
929 /*
930 * ****************************************************************************
931 *
932 * make_raw_assoc_iscsi:
933 * Make raw SCN data with a Discovery Domain member association.
934 *
935 * obj - the member association object.
936 * return - the raw SCN data.
937 *
938 * ****************************************************************************
939 */
940 static scn_raw_t *
make_raw_assoc_iscsi(isns_obj_t * obj)941 make_raw_assoc_iscsi(
942 isns_obj_t *obj
943 )
944 {
945 uint32_t uid;
946 uint32_t dd_id;
947 uint32_t nt;
948
949 lookup_ctrl_t lc;
950 isns_attr_t *attr;
951
952 scn_raw_t *raw;
953 uchar_t *iscsi;
954 uint32_t ilen;
955
956 uid = get_obj_uid(obj);
957 dd_id = get_parent_uid(obj);
958
959 SET_UID_LCP(&lc, OBJ_ISCSI, uid);
960
961 nt = cache_lookup(&lc, NULL, cb_get_node_type);
962
963 attr = &obj->attrs[ATTR_INDEX_ASSOC_ISCSI(ISNS_DD_ISCSI_NAME_ATTR_ID)];
964
965 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
966 ilen = attr->len;
967 iscsi = (uchar_t *)malloc(ilen);
968 if (raw != NULL && iscsi != NULL) {
969 /* copy the iscsi storage node name */
970 (void) strcpy((char *)iscsi, (char *)attr->value.ptr);
971
972 raw->type = obj->type;
973 raw->uid = uid;
974 raw->iscsi = iscsi;
975 raw->ref = 0;
976 raw->ilen = ilen;
977 raw->nt = nt;
978 raw->ip = NULL;
979 raw->dd_id = dd_id;
980 raw->dds_id = 0;
981 } else {
982 free(raw);
983 free(iscsi);
984 raw = NULL;
985 isnslog(LOG_DEBUG, "make_raw_assoc_iscsi", "malloc failed.");
986 }
987
988 return (raw);
989 }
990
991 /*
992 * ****************************************************************************
993 *
994 * make_raw_assoc_dd:
995 * Make raw SCN data with a Discovery Domain Set member association.
996 *
997 * obj - the member association object.
998 * return - the raw SCN data.
999 *
1000 * ****************************************************************************
1001 */
1002 static scn_raw_t *
make_raw_assoc_dd(isns_obj_t * obj)1003 make_raw_assoc_dd(
1004 isns_obj_t *obj
1005 )
1006 {
1007 scn_raw_t *raw;
1008
1009 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
1010 if (raw != NULL) {
1011 raw->type = obj->type;
1012 raw->uid = 0;
1013 raw->iscsi = NULL;
1014 raw->ref = 0;
1015 raw->ilen = 0;
1016 raw->nt = 0;
1017 raw->ip = NULL;
1018 raw->dd_id = get_obj_uid(obj);
1019 raw->dds_id = get_parent_uid(obj);
1020 } else {
1021 isnslog(LOG_DEBUG, "make_raw_assoc_dd", "malloc failed.");
1022 }
1023
1024 return (raw);
1025 }
1026
1027 /*
1028 * ****************************************************************************
1029 *
1030 * scn_gen_entity:
1031 * Generate SCN with the raw SCN data from a Network Entity object.
1032 *
1033 * raw - the raw SCN data.
1034 * return - the SCN.
1035 *
1036 * ****************************************************************************
1037 */
1038 static scn_text_t *
scn_gen_entity(scn_raw_t * raw)1039 scn_gen_entity(
1040 /* LINTED E_FUNC_ARG_UNUSED */
1041 scn_raw_t *raw
1042 )
1043 {
1044 return (NULL);
1045 }
1046
1047 /*
1048 * ****************************************************************************
1049 *
1050 * scn_gen_iscsi:
1051 * Generate SCN with the raw SCN data from a Storage Node object.
1052 *
1053 * raw - the raw SCN data.
1054 * return - the SCN.
1055 *
1056 * ****************************************************************************
1057 */
1058 static scn_text_t *
scn_gen_iscsi(scn_raw_t * raw)1059 scn_gen_iscsi(
1060 scn_raw_t *raw
1061 )
1062 {
1063 scn_text_t *text;
1064
1065 text = (scn_text_t *)malloc(sizeof (scn_text_t));
1066 if (text != NULL) {
1067 text->flag = 0;
1068 text->ref = 1; /* start with 1 */
1069 text->uid = raw->uid;
1070 text->iscsi = raw->iscsi;
1071 raw->ref ++;
1072 text->ilen = raw->ilen;
1073 text->nt = raw->nt;
1074 text->dd_id = raw->dd_id;
1075 text->dds_id = raw->dds_id;
1076 text->next = NULL;
1077 } else {
1078 isnslog(LOG_DEBUG, "scn_gen_iscsi", "malloc failed.");
1079 }
1080 return (text);
1081 }
1082
1083 /*
1084 * ****************************************************************************
1085 *
1086 * scn_gen_portal:
1087 * Generate SCN with the raw SCN data from a Portal object.
1088 *
1089 * raw - the raw SCN data.
1090 * return - the SCN.
1091 *
1092 * ****************************************************************************
1093 */
1094 static scn_text_t *
scn_gen_portal(scn_raw_t * raw)1095 scn_gen_portal(
1096 scn_raw_t *raw
1097 )
1098 {
1099 in6_addr_t *ip;
1100 uint32_t port;
1101
1102 uint32_t pg_uid, uid;
1103 lookup_ctrl_t pg_lc, lc;
1104
1105 uint32_t nt;
1106 uchar_t *name;
1107 int ilen;
1108
1109 scn_text_t *text, *l = NULL;
1110
1111 ip = raw->ip;
1112 port = raw->port;
1113
1114 pg_lc.curr_uid = 0;
1115 pg_lc.type = OBJ_PG;
1116 pg_lc.id[0] = ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID);
1117 pg_lc.op[0] = OP_MEMORY_IP6;
1118 pg_lc.data[0].ip = ip;
1119 pg_lc.id[1] = ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID);
1120 pg_lc.op[1] = OP_INTEGER;
1121 pg_lc.data[1].ui = port;
1122 pg_lc.op[2] = 0;
1123
1124 SET_UID_LCP(&lc, OBJ_ISCSI, 0);
1125
1126 lc.id[1] = ISNS_ISCSI_NAME_ATTR_ID;
1127 lc.id[2] = ISNS_ISCSI_NODE_TYPE_ATTR_ID;
1128 lc.data[1].ptr = NULL;
1129
1130 /* get a pg which is associated to the portal */
1131 uid = cache_lookup(&pg_lc, &pg_uid, cb_pg_node);
1132 while (pg_uid != 0) {
1133 if (uid != 0) {
1134 lc.data[0].ui = uid;
1135 (void) cache_lookup(&lc, NULL, cb_clone_attrs);
1136 name = lc.data[1].ptr;
1137 if (name != NULL) {
1138 nt = lc.data[2].ui;
1139 text = (scn_text_t *)malloc(
1140 sizeof (scn_text_t));
1141 if (text != NULL) {
1142 text->flag = 0;
1143 text->ref = 1; /* start with 1 */
1144 text->uid = uid;
1145 text->iscsi = name;
1146 ilen = strlen((char *)name);
1147 ilen += 4 - (ilen % 4);
1148 text->ilen = ilen;
1149 text->nt = nt;
1150 text->dd_id = 0;
1151 text->dds_id = 0;
1152 text->next = l;
1153 l = text;
1154 } else {
1155 free(name);
1156 isnslog(LOG_DEBUG, "scn_gen_portal",
1157 "malloc failed.");
1158 }
1159 lc.data[1].ptr = NULL;
1160 } else {
1161 isnslog(LOG_WARNING, "scn_gen_portal",
1162 "cannot get node name.");
1163 }
1164 }
1165
1166 /* get the next pg */
1167 pg_lc.curr_uid = pg_uid;
1168 uid = cache_lookup(&pg_lc, &pg_uid, cb_pg_node);
1169 }
1170
1171 /* update the iscsi storage node object */
1172 raw->event = ISNS_OBJECT_UPDATED;
1173
1174 return (l);
1175 }
1176
1177 /*
1178 * ****************************************************************************
1179 *
1180 * scn_gen_assoc_dd:
1181 * Generate SCN with the raw SCN data from a DD membership object.
1182 *
1183 * raw - the raw SCN data.
1184 * return - the SCN.
1185 *
1186 * ****************************************************************************
1187 */
1188 static scn_text_t *
scn_gen_assoc_dd(scn_raw_t * raw)1189 scn_gen_assoc_dd(
1190 /* LINTED E_FUNC_ARG_UNUSED */
1191 scn_raw_t *raw
1192 )
1193 {
1194 return (NULL);
1195 }
1196
1197 /*
1198 * ****************************************************************************
1199 *
1200 * make_scn:
1201 * Make a SCN with an event and an object.
1202 *
1203 * event - the event.
1204 * obj - the object.
1205 * return - always successful (0).
1206 *
1207 * ****************************************************************************
1208 */
1209 int
make_scn(uint32_t event,isns_obj_t * obj)1210 make_scn(
1211 uint32_t event,
1212 isns_obj_t *obj
1213 )
1214 {
1215 scn_raw_t *raw = NULL;
1216
1217 scn_raw_t *(*f)(isns_obj_t *) = make_raw[obj->type];
1218
1219 if (f != NULL) {
1220 /* make raw scn data */
1221 raw = f(obj);
1222 }
1223 if (raw != NULL) {
1224 /* trigger an scn event */
1225 raw->event = event;
1226 (void) queue_msg_set(scn_q, SCN_SET, (void *)raw);
1227 }
1228
1229 return (0);
1230 }
1231
1232 /*
1233 * data structure of the SCN state transition table.
1234 */
1235 typedef struct scn_tbl {
1236 int state;
1237 uint32_t event;
1238 isns_type_t type;
1239 int (*sf)(scn_raw_t *);
1240 int next_state;
1241 } scn_tbl_t;
1242
1243 /*
1244 * the SCN state transition table.
1245 */
1246 static const scn_tbl_t stbl[] = {
1247 { -1, 0, OBJ_PG, NULL, 0 },
1248 { -1, 0, OBJ_DD, NULL, 0 },
1249 { -1, 0, OBJ_DDS, NULL, 0 },
1250
1251 { 0, ISNS_OBJECT_ADDED, OBJ_ENTITY, NULL, 1 },
1252 { 1, ISNS_OBJECT_ADDED, OBJ_ISCSI, sf_gen, 1 },
1253 { 1, ISNS_OBJECT_ADDED, 0, NULL, 1 },
1254
1255 { 0, ISNS_OBJECT_UPDATED, OBJ_ENTITY, sf_gen, 2 },
1256 { 2, ISNS_OBJECT_UPDATED, 0, NULL, 2 },
1257 { 2, ISNS_OBJECT_ADDED, OBJ_ISCSI, sf_gen, 2 },
1258 { 2, ISNS_OBJECT_ADDED, 0, NULL, 2 },
1259
1260 { 0, ISNS_OBJECT_REMOVED, OBJ_ENTITY, NULL, 3 },
1261 { 0, ISNS_OBJECT_REMOVED, 0, sf_gen, 4 },
1262 { 3, ISNS_OBJECT_REMOVED, OBJ_ISCSI, sf_gen, 3 },
1263 { 3, ISNS_OBJECT_REMOVED, 0, NULL, 3 },
1264 { 4, ISNS_OBJECT_REMOVED, 0, sf_gen, 4 },
1265
1266 { 0, ISNS_MEMBER_ADDED, OBJ_ASSOC_ISCSI, sf_gen, 5 },
1267 { 5, ISNS_MEMBER_ADDED, OBJ_ASSOC_ISCSI, sf_gen, 5 },
1268
1269 { 0, ISNS_MEMBER_ADDED, OBJ_ASSOC_DD, sf_gen, 6 },
1270 { 6, ISNS_MEMBER_ADDED, OBJ_ASSOC_DD, sf_gen, 6 },
1271
1272 { 0, ISNS_MEMBER_REMOVED, OBJ_ASSOC_ISCSI, sf_gen, 7 },
1273 { 7, ISNS_MEMBER_REMOVED, OBJ_ASSOC_ISCSI, sf_gen, 7 },
1274
1275 { 0, ISNS_MEMBER_REMOVED, OBJ_ASSOC_DD, sf_gen, 8 },
1276 { 8, ISNS_MEMBER_REMOVED, OBJ_ASSOC_DD, sf_gen, 8 },
1277
1278 { -1, 0, 0, sf_error, -1 }
1279 };
1280
1281 /*
1282 * ****************************************************************************
1283 *
1284 * scn_disp1:
1285 * Dispatch one SCN to one SCN entry.
1286 *
1287 * event - the event.
1288 * p - the SCN entry.
1289 * t - the SCN.
1290 * return - always successful (0).
1291 *
1292 * ****************************************************************************
1293 */
1294 static int
scn_disp1(uint32_t event,scn_registry_t * p,scn_text_t * t)1295 scn_disp1(
1296 uint32_t event,
1297 scn_registry_t *p,
1298 scn_text_t *t
1299 )
1300 {
1301 scn_t *s, *r = NULL;
1302 scn_list_t *l, **lp;
1303
1304 s = p->scn;
1305
1306 while (s != NULL) {
1307 if (s->event == event) {
1308 l = s->data.list;
1309 do {
1310 if (l->data.text->uid == t->uid) {
1311 /* duplicated */
1312 return (0);
1313 }
1314 lp = &l->next;
1315 l = *lp;
1316 } while (l != NULL);
1317 break;
1318 }
1319 r = s;
1320 s = s->next;
1321 }
1322
1323 l = (scn_list_t *)malloc(sizeof (scn_list_t));
1324 if (l != NULL) {
1325 if (s == NULL) {
1326 s = (scn_t *)malloc(sizeof (scn_t));
1327 if (s != NULL) {
1328 s->event = event;
1329 s->next = NULL;
1330 if (r != NULL) {
1331 r->next = s;
1332 } else {
1333 p->scn = s;
1334 }
1335 lp = &s->data.list;
1336 } else {
1337 free(l);
1338 isnslog(LOG_DEBUG, "scn_disp1",
1339 "malloc scn failed.\n");
1340 return (0);
1341 }
1342 }
1343
1344 t->ref ++;
1345 l->data.text = t;
1346 l->next = NULL;
1347 *lp = l;
1348 } else {
1349 isnslog(LOG_DEBUG, "scn_disp1",
1350 "malloc list failed.\n");
1351 }
1352
1353 return (0);
1354 }
1355
1356 /*
1357 * ****************************************************************************
1358 *
1359 * scn_disp1:
1360 * Dispatch one SCN to every SCN entry and update the dispatch status.
1361 *
1362 * event - the event.
1363 * text - the SCN.
1364 * return - always successful (0).
1365 *
1366 * ****************************************************************************
1367 */
1368 static int
scn_disp(uint32_t event,scn_text_t * text)1369 scn_disp(
1370 uint32_t event,
1371 scn_text_t *text
1372 )
1373 {
1374 scn_registry_t *registry, *p;
1375 uint32_t dd_id = 0;
1376
1377 scn_text_t *t;
1378
1379 uint32_t e;
1380
1381 registry = scn_registry;
1382
1383 t = text;
1384 while (t != NULL) {
1385 e = event;
1386 if (t->flag == 0) {
1387 if (e & ISNS_MEMBER_ADDED) {
1388 e |= ISNS_OBJECT_ADDED;
1389 } else if (e & ISNS_MEMBER_REMOVED) {
1390 e |= ISNS_OBJECT_REMOVED;
1391 }
1392 }
1393 p = registry;
1394 while (p != NULL) {
1395 if (SCN_TEST(e, p->bitmap, p->uid, t->uid, t->nt)) {
1396 if (p->bitmap & ISNS_MGMT_REG) {
1397 /* management scn are not bound */
1398 /* by discovery domain service. */
1399 dd_id = 1;
1400 } else {
1401 dd_id = 0;
1402 /* lock the cache for reading */
1403 (void) cache_lock_read();
1404 /* verify common dd */
1405 do {
1406 dd_id = get_common_dd(
1407 p->uid,
1408 t->uid,
1409 dd_id);
1410 } while (dd_id > 0 &&
1411 is_dd_active(dd_id) == 0);
1412 /* unlock the cache */
1413 (void) cache_unlock_nosync();
1414 }
1415 if (dd_id != 0) {
1416 (void) scn_disp1(e, p, t);
1417 }
1418 }
1419 p = p->next;
1420 }
1421 t = t->next;
1422 }
1423
1424 while (text != NULL) {
1425 t = text->next;
1426 /* clean up the scn text(s) which nobody cares about. */
1427 free_scn_text(text);
1428 text = t;
1429 }
1430
1431 if (dd_id != 0) {
1432 /* scn(s) are dispatched. */
1433 scn_dispatched = 1;
1434 }
1435
1436 return (0);
1437 }
1438
1439 /*
1440 * ****************************************************************************
1441 *
1442 * sf_gen:
1443 * State transition function which generates and dispatches SCN(s).
1444 *
1445 * raw - the raw SCN data.
1446 * return - always successful (0).
1447 *
1448 * ****************************************************************************
1449 */
1450 static int
sf_gen(scn_raw_t * raw)1451 sf_gen(
1452 scn_raw_t *raw
1453 )
1454 {
1455 uint32_t event;
1456
1457 scn_text_t *(*gen)(scn_raw_t *);
1458 scn_text_t *text = NULL;
1459
1460 gen = scn_gen[raw->type];
1461 if (gen != NULL) {
1462 text = gen(raw);
1463 }
1464
1465 event = raw->event;
1466 if (text != NULL) {
1467 (void) scn_disp(event, text);
1468 }
1469
1470 return (0);
1471 }
1472
1473 /*
1474 * ****************************************************************************
1475 *
1476 * sf_error:
1477 * State transition function for an error state. It free any SCN(s)
1478 * which have been generated and dispatched previously.
1479 *
1480 * raw - the raw SCN data.
1481 * return - always successful (0).
1482 *
1483 * ****************************************************************************
1484 */
1485 static int
sf_error(scn_raw_t * raw)1486 sf_error(
1487 /* LINTED E_FUNC_ARG_UNUSED */
1488 scn_raw_t *raw
1489 )
1490 {
1491 free_scn();
1492
1493 return (0);
1494 }
1495
1496 /*
1497 * ****************************************************************************
1498 *
1499 * scn_transition:
1500 * Performs the state transition when a SCN event occurs.
1501 *
1502 * state - the previous state.
1503 * raw - the raw SCN data.
1504 * return - the next state.
1505 *
1506 * ****************************************************************************
1507 */
1508 static int
scn_transition(int state,scn_raw_t * raw)1509 scn_transition(
1510 int state,
1511 scn_raw_t *raw
1512 )
1513 {
1514 uint32_t event = raw->event;
1515 isns_type_t type = raw->type;
1516
1517 int new_state = state;
1518
1519 const scn_tbl_t *tbl;
1520
1521 tbl = &stbl[0];
1522 for (;;) {
1523 if ((tbl->state == -1 || tbl->state == state) &&
1524 (tbl->event == 0 || tbl->event == event) &&
1525 (tbl->type == 0 || tbl->type == type)) {
1526 if (tbl->next_state != 0) {
1527 new_state = tbl->next_state;
1528 }
1529 if (tbl->sf != NULL) {
1530 tbl->sf(raw);
1531 }
1532 break;
1533 }
1534 tbl ++;
1535 }
1536
1537 if (new_state == -1) {
1538 isnslog(LOG_DEBUG, "scn_transition",
1539 "prev state: %d new event: 0x%x new object: %d.\n",
1540 state, event, type);
1541 new_state = 0;
1542 }
1543
1544 state = new_state;
1545
1546 return (state);
1547 }
1548
1549 /*
1550 * ****************************************************************************
1551 *
1552 * connect_to:
1553 * Create socket connection with peer network portal.
1554 *
1555 * sz - the size of the ip addr.
1556 * in - the ipv4 address.
1557 * in6 - the ipv6 address.
1558 * port2- the port info.
1559 * return - the socket descriptor.
1560 *
1561 * ****************************************************************************
1562 */
1563 int
connect_to(int sz,in_addr_t in,in6_addr_t * in6,uint32_t port2)1564 connect_to(
1565 int sz,
1566 in_addr_t in,
1567 /* LINTED E_FUNC_ARG_UNUSED */
1568 in6_addr_t *in6,
1569 uint32_t port2
1570 )
1571 {
1572 int so = -1;
1573
1574 union {
1575 struct sockaddr sin;
1576 struct sockaddr_in in;
1577 struct sockaddr_in6 in6;
1578 } ca = { 0 };
1579
1580 int tcp;
1581 uint16_t port;
1582
1583 tcp = (port2 & 0x10000) == 0 ? 1 : 0;
1584 port = (uint16_t)(port2 & 0xFFFF);
1585 if (sz == sizeof (in_addr_t)) {
1586 if (tcp != 0) {
1587 so = socket(AF_INET, SOCK_STREAM, 0);
1588 if (so != -1) {
1589 ca.in.sin_family = AF_INET;
1590 ca.in.sin_port = htons(port);
1591 ca.in.sin_addr.s_addr = in;
1592 if (connect(so, &ca.sin, sizeof (ca.in)) !=
1593 0) {
1594 isnslog(LOG_DEBUG, "connect_to",
1595 "connect() failed %%m.");
1596 (void) close(so);
1597 so = -1;
1598 }
1599 } else {
1600 isnslog(LOG_DEBUG, "connect_to",
1601 "socket() failed %%m.");
1602 }
1603 } else {
1604 /* FIXME: UDP support */
1605 isnslog(LOG_DEBUG, "connect_to", "No UDP support.");
1606 }
1607 } else {
1608 /* FIXME: IPv6 support */
1609 isnslog(LOG_DEBUG, "connect_to", "No IPv6 support.");
1610 }
1611
1612 return (so);
1613 }
1614
1615 /*
1616 * ****************************************************************************
1617 *
1618 * emit_scn:
1619 * Emit the SCN to any portal of the peer storage node.
1620 *
1621 * list - the list of portal.
1622 * pdu - the SCN packet.
1623 * pl - the SCN packet payload length.
1624 * return - always successful (0).
1625 *
1626 * ****************************************************************************
1627 */
1628 static int
emit_scn(scn_list_t * list,isns_pdu_t * pdu,size_t pl)1629 emit_scn(
1630 scn_list_t *list,
1631 isns_pdu_t *pdu,
1632 size_t pl
1633 )
1634 {
1635 int so = 0;
1636 scn_list_t *l;
1637 scn_portal_t *p;
1638
1639 isns_pdu_t *rsp = NULL;
1640 size_t rsp_sz;
1641
1642 pdu->version = htons((uint16_t)ISNSP_VERSION);
1643 pdu->func_id = htons((uint16_t)ISNS_SCN);
1644 pdu->xid = htons(get_server_xid());
1645
1646 l = list;
1647 while (l != NULL) {
1648 p = l->data.portal;
1649 so = connect_to(p->sz, p->ip.in, p->ip.in6, p->port);
1650 if (so != -1) {
1651 if (isns_send_pdu(so, pdu, pl) == 0) {
1652 /* This may help Solaris iSCSI Initiator */
1653 /* not to panic frequently. */
1654 (void) isns_rcv_pdu(so, &rsp, &rsp_sz,
1655 ISNS_RCV_SHORT_TIMEOUT);
1656 } else {
1657 isnslog(LOG_DEBUG, "emit_scn",
1658 "sending packet failed.");
1659 }
1660 (void) close(so);
1661 /* p->so = so; */
1662 break;
1663 }
1664 l = l->next;
1665 }
1666
1667 if (rsp != NULL) {
1668 #ifdef DEBUG
1669 dump_pdu1(rsp);
1670 #endif
1671 free(rsp);
1672 }
1673
1674 return (0);
1675 }
1676
1677 /*
1678 * ****************************************************************************
1679 *
1680 * scn_trigger1:
1681 * Trigger one SCN for one SCN entry.
1682 *
1683 * t - the time that SCN is being triggered.
1684 * p - the SCN entry.
1685 * return - always successful (0).
1686 *
1687 * ****************************************************************************
1688 */
1689 static int
scn_trigger1(time_t t,scn_registry_t * p)1690 scn_trigger1(
1691 time_t t,
1692 scn_registry_t *p
1693 )
1694 {
1695 int ec;
1696
1697 isns_pdu_t *pdu = NULL;
1698 size_t sz;
1699 size_t pl;
1700
1701 scn_t *s;
1702 scn_list_t *l;
1703 scn_text_t *x;
1704
1705 union {
1706 uint32_t i32;
1707 uint64_t i64;
1708 } u;
1709
1710 #ifdef DEBUG
1711 char buff[1024] = { 0 };
1712 char *logbuff = buff;
1713 #endif
1714
1715 ec = pdu_reset_scn(&pdu, &pl, &sz);
1716 if (pdu == NULL) {
1717 goto scn_done;
1718 }
1719
1720 /* add destination attribute */
1721 ec = pdu_add_tlv(&pdu, &pl, &sz,
1722 ISNS_ISCSI_NAME_ATTR_ID,
1723 p->nlen,
1724 (void *)p->name, 0);
1725 if (ec != 0) {
1726 goto scn_done;
1727 }
1728
1729 #ifdef DEBUG
1730 sprintf(logbuff, "==>%s ", p->name);
1731 logbuff += strlen(logbuff);
1732 #endif
1733
1734 /* add timestamp */
1735 u.i64 = BE_64((uint64_t)t);
1736 ec = pdu_add_tlv(&pdu, &pl, &sz,
1737 ISNS_TIMESTAMP_ATTR_ID,
1738 8,
1739 (void *)&u.i64, 1);
1740
1741 s = p->scn;
1742 while (s != NULL && ec == 0) {
1743 u.i32 = htonl(s->event);
1744 ec = pdu_add_tlv(&pdu, &pl, &sz,
1745 ISNS_ISCSI_SCN_BITMAP_ATTR_ID,
1746 4,
1747 (void *)&u.i32, 1);
1748 #ifdef DEBUG
1749 sprintf(logbuff, "EVENT [%d] ", s->event);
1750 logbuff += strlen(logbuff);
1751 #endif
1752 l = s->data.list;
1753 while (l != NULL && ec == 0) {
1754 x = l->data.text;
1755 if (x->flag == 0) {
1756 ec = pdu_add_tlv(&pdu, &pl, &sz,
1757 ISNS_ISCSI_NAME_ATTR_ID,
1758 x->ilen, (void *)x->iscsi, 0);
1759 #ifdef DEBUG
1760 sprintf(logbuff, "FROM [%s] ", x->iscsi);
1761 logbuff += strlen(logbuff);
1762 #endif
1763 if (ec == 0 &&
1764 (p->bitmap &
1765 (ISNS_MEMBER_ADDED |
1766 ISNS_MEMBER_REMOVED))) {
1767 /* management SCN */
1768 u.i32 = htonl(x->dd_id);
1769 ec = pdu_add_tlv(&pdu, &pl, &sz,
1770 ISNS_DD_ID_ATTR_ID,
1771 4, (void *)&u.i32, 1);
1772 #ifdef DEBUG
1773 sprintf(logbuff, "IN DD [%d] ",
1774 x->dd_id);
1775 logbuff += strlen(logbuff);
1776 #endif
1777 }
1778 } else {
1779 /* add(remove) dd to(from) dd-set */
1780 u.i32 = htonl(x->dd_id);
1781 ec = pdu_add_tlv(&pdu, &pl, &sz,
1782 ISNS_DD_ID_ATTR_ID,
1783 4, (void *)&u.i32, 1);
1784 u.i32 = htonl(x->dds_id);
1785 if (ec == 0) {
1786 ec = pdu_add_tlv(&pdu, &pl, &sz,
1787 ISNS_DD_ID_ATTR_ID,
1788 4, (void *)&u.i32, 1);
1789 }
1790 #ifdef DEBUG
1791 sprintf(logbuff, "FROM [%d] ", x->dd_id);
1792 logbuff += strlen(logbuff);
1793 sprintf(logbuff, "IN [%d] ", x->dds_id);
1794 logbuff += strlen(logbuff);
1795 #endif
1796 }
1797 l = l->next;
1798 }
1799 s = s->next;
1800 }
1801
1802 scn_done:
1803 if (ec == 0) {
1804 #ifdef DEBUG
1805 isnslog(LOG_DEBUG, "scn_trigger1", buff);
1806 #endif
1807 ec = emit_scn(p->portal.l, pdu, pl);
1808 } else {
1809 isnslog(LOG_DEBUG, "scn_trigger1", " failed.\n");
1810 }
1811
1812 free(pdu);
1813
1814 return (0);
1815 }
1816
1817 /*
1818 * ****************************************************************************
1819 *
1820 * scn_trigger:
1821 * Trigger one SCN for every SCN entry.
1822 *
1823 * return - always successful (0).
1824 *
1825 * ****************************************************************************
1826 */
1827 static int
scn_trigger()1828 scn_trigger(
1829 )
1830 {
1831 time_t t;
1832 scn_registry_t *p;
1833
1834 t = time(NULL);
1835
1836 p = scn_registry;
1837 while (p != NULL) {
1838 if (p->scn != NULL) {
1839 (void) scn_trigger1(t, p);
1840 }
1841 p = p->next;
1842 }
1843
1844 return (0);
1845 }
1846
1847 /*
1848 * global functions.
1849 */
1850
1851 /*
1852 * ****************************************************************************
1853 *
1854 * scn_list_load:
1855 * Load one SCN entry and add it to the SCN entry list.
1856 *
1857 * uid - the Storage Node object UID.
1858 * node - the Storage Node name.
1859 * nlen - the length of the name.
1860 * bitmap - the SCN bitmap.
1861 * return - error code.
1862 *
1863 * ****************************************************************************
1864 */
1865 int
scn_list_load(uint32_t uid,uchar_t * node,uint32_t nlen,uint32_t bitmap)1866 scn_list_load(
1867 uint32_t uid,
1868 uchar_t *node,
1869 uint32_t nlen,
1870 uint32_t bitmap
1871 )
1872 {
1873 int ec = 0;
1874
1875 scn_registry_t *list;
1876 uchar_t *name;
1877
1878 list = (scn_registry_t *)malloc(sizeof (scn_registry_t));
1879 name = (uchar_t *)malloc(nlen);
1880
1881 if (list != NULL && name != NULL) {
1882 list->uid = uid;
1883 (void) strcpy((char *)name, (char *)node);
1884 list->name = name;
1885 list->nlen = nlen;
1886 list->bitmap = bitmap;
1887 list->portal.l = NULL;
1888 list->scn = NULL;
1889 list->next = NULL;
1890 ASSERT(scn_q == NULL);
1891 (void) scn_list_add(list);
1892 } else {
1893 free(list);
1894 free(name);
1895 ec = ISNS_RSP_INTERNAL_ERROR;
1896 }
1897
1898 return (ec);
1899 }
1900
1901 /*
1902 * ****************************************************************************
1903 *
1904 * verify_scn_portal:
1905 * Extract and verify portals for every SCN entry(s) after they are
1906 * loaded from data store, for those which do not have a SCN portal,
1907 * remove it from the SCN entry list.
1908 *
1909 * return - 1: error occurs, otherwise 0.
1910 *
1911 * ****************************************************************************
1912 */
1913 int
verify_scn_portal()1914 verify_scn_portal(
1915 )
1916 {
1917 scn_registry_t **pp, *e;
1918 scn_portal_t *p;
1919
1920 pp = &scn_registry;
1921 while (*pp != NULL) {
1922 e = *pp;
1923 p = extract_scn_portal(e->name);
1924 if (p != NULL) {
1925 if (scn_add_portal(e, p) != 0) {
1926 return (1);
1927 }
1928 }
1929 if (e->portal.l != NULL) {
1930 pp = &e->next;
1931 } else {
1932 /* remove this entry */
1933 *pp = e->next;
1934 free_entry(e);
1935 }
1936 /* free the unused portal(s) */
1937 free_portal(p);
1938 }
1939
1940 return (0);
1941 }
1942
1943 /*
1944 * ****************************************************************************
1945 *
1946 * add_scn_entry:
1947 * Add a SCN entry.
1948 *
1949 * node - the Storage Node name.
1950 * nlen - the length of the name.
1951 * bitmap - the SCN bitmap.
1952 * return - error code.
1953 *
1954 * ****************************************************************************
1955 */
1956 int
add_scn_entry(uchar_t * node,uint32_t nlen,uint32_t bitmap)1957 add_scn_entry(
1958 uchar_t *node,
1959 uint32_t nlen,
1960 uint32_t bitmap
1961 )
1962 {
1963 int ec = 0;
1964
1965 uint32_t mgmt;
1966 scn_portal_t *p;
1967
1968 lookup_ctrl_t lc;
1969 uint32_t uid;
1970 scn_registry_t *e;
1971 uchar_t *name;
1972
1973 mgmt = bitmap & (
1974 ISNS_MGMT_REG |
1975 ISNS_MEMBER_REMOVED |
1976 ISNS_MEMBER_ADDED);
1977
1978 if ((mgmt > 0 &&
1979 (mgmt_scn == 0 ||
1980 mgmt < ISNS_MGMT_REG ||
1981 is_control_node(node) == 0)) ||
1982 (p = extract_scn_portal(node)) == NULL) {
1983 return (ISNS_RSP_SCN_REGIS_REJECTED);
1984 }
1985
1986 e = (scn_registry_t *)malloc(sizeof (scn_registry_t));
1987 name = (uchar_t *)malloc(nlen);
1988 if (e != NULL && name != NULL) {
1989 lc.type = OBJ_ISCSI;
1990 lc.curr_uid = 0;
1991 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
1992 lc.data[0].ptr = node;
1993 lc.op[0] = OP_STRING;
1994 lc.op[1] = 0;
1995 lc.data[2].ui = bitmap;
1996 ec = cache_lookup(&lc, &uid, cb_update_scn_bitmap);
1997 if (uid == 0) {
1998 ec = ISNS_RSP_SCN_REGIS_REJECTED;
1999 }
2000 if (ec == 0) {
2001 e->uid = uid;
2002 (void) strcpy((char *)name, (char *)node);
2003 e->name = name;
2004 e->nlen = nlen;
2005 e->bitmap = bitmap;
2006 e->portal.p = p;
2007 e->scn = NULL;
2008 e->next = NULL;
2009 (void) queue_msg_set(scn_q, SCN_ADD, (void *)e);
2010 }
2011 } else {
2012 ec = ISNS_RSP_INTERNAL_ERROR;
2013 }
2014
2015 if (ec != 0) {
2016 free(e);
2017 free(name);
2018 free_portal(p);
2019 }
2020
2021 return (ec);
2022 }
2023
2024 /*
2025 * ****************************************************************************
2026 *
2027 * remove_scn_entry:
2028 * Remove a SCN entry.
2029 *
2030 * node - the Storage Node name.
2031 * return - error code.
2032 *
2033 * ****************************************************************************
2034 */
2035 int
remove_scn_entry(uchar_t * node)2036 remove_scn_entry(
2037 uchar_t *node
2038 )
2039 {
2040 int ec = 0;
2041
2042 lookup_ctrl_t lc;
2043 uint32_t uid;
2044
2045 lc.type = OBJ_ISCSI;
2046 lc.curr_uid = 0;
2047 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
2048 lc.data[0].ptr = node;
2049 lc.op[0] = OP_STRING;
2050 lc.op[1] = 0;
2051 lc.data[2].ui = 0;
2052 ec = cache_lookup(&lc, &uid, cb_update_scn_bitmap);
2053 if (ec == 0 && uid != 0) {
2054 (void) queue_msg_set(scn_q, SCN_REMOVE, (void *)uid);
2055 }
2056
2057 return (ec);
2058 }
2059
2060 /*
2061 * ****************************************************************************
2062 *
2063 * remove_scn_portal:
2064 * Remove a portal from every SCN entry.
2065 *
2066 * uid - the Portal object UID.
2067 * return - alrays successful (0).
2068 *
2069 * ****************************************************************************
2070 */
2071 int
remove_scn_portal(uint32_t uid)2072 remove_scn_portal(
2073 uint32_t uid
2074 )
2075 {
2076 (void) queue_msg_set(scn_q, SCN_REMOVE_P, (void *)uid);
2077
2078 return (0);
2079 }
2080
2081 /*
2082 * ****************************************************************************
2083 *
2084 * scn_proc:
2085 * The entry point of the SCN thread. It listens on the SCN message
2086 * queue and process every SCN related stuff.
2087 *
2088 * arg - nothing.
2089 * return - NULL.
2090 *
2091 * ****************************************************************************
2092 */
2093 void *
scn_proc(void * arg)2094 scn_proc(
2095 /* LINTED E_FUNC_ARG_UNUSED */
2096 void *arg
2097 )
2098 {
2099 int state = 0;
2100
2101 scn_raw_t *raw;
2102 msg_text_t *msg;
2103
2104 for (;;) {
2105 msg = queue_msg_get(scn_q);
2106 switch (msg->id) {
2107 case SCN_ADD:
2108 (void) scn_list_add((scn_registry_t *)msg->data);
2109 break;
2110 case SCN_REMOVE:
2111 (void) scn_list_remove((uint32_t)msg->data);
2112 break;
2113 case SCN_REMOVE_P:
2114 (void) scn_remove_portal((uint32_t)msg->data);
2115 break;
2116 case SCN_SET:
2117 raw = (scn_raw_t *)msg->data;
2118 state = scn_transition(state, raw);
2119 /* free the raw data */
2120 free_raw(raw);
2121 break;
2122 case SCN_TRIGGER:
2123 if (scn_dispatched != 0) {
2124 (void) scn_trigger();
2125 }
2126 case SCN_IGNORE:
2127 /* clean the scn(s) */
2128 free_scn();
2129 /* reset the state */
2130 state = 0;
2131 /* reset the scn_dispatched flag */
2132 scn_dispatched = 0;
2133 break;
2134 case SCN_STOP:
2135 queue_msg_free(msg);
2136 return (NULL);
2137 default:
2138 break;
2139 }
2140 queue_msg_free(msg);
2141 }
2142 }
2143