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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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