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 2009 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 <pthread.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <netinet/in.h> 34 #include <arpa/inet.h> 35 36 #include "isns_server.h" 37 #include "isns_msgq.h" 38 #include "isns_htab.h" 39 #include "isns_cache.h" 40 #include "isns_pdu.h" 41 #include "isns_obj.h" 42 #include "isns_dd.h" 43 #include "isns_func.h" 44 #include "isns_dseng.h" 45 #include "isns_log.h" 46 #include "isns_scn.h" 47 #include "isns_utils.h" 48 #include "isns_esi.h" 49 50 /* 51 * external variables 52 */ 53 #ifdef DEBUG 54 extern int verbose_mc; 55 extern void print_object(char *, isns_obj_t *); 56 #endif 57 58 extern msg_queue_t *sys_q; 59 extern msg_queue_t *scn_q; 60 61 extern pthread_mutex_t el_mtx; 62 63 extern int cache_flag; 64 65 /* 66 * global data 67 */ 68 69 /* 70 * local variables 71 */ 72 /* type of parent object */ 73 const int TYPE_OF_PARENT[MAX_OBJ_TYPE_FOR_SIZE] = { 74 0, 75 0, 76 ISCSI_PARENT_TYPE, 77 PORTAL_PARENT_TYPE, 78 PG_PARENT_TYPE, 79 0, /* OBJ_DD */ 80 0, /* OBJ_DDS */ 81 0, /* MAX_OBJ_TYPE */ 82 0, /* OBJ_DUMMY1 */ 83 0, /* OBJ_DUMMY2 */ 84 0, /* OBJ_DUMMY3 */ 85 0, /* OBJ_DUMMY4 */ 86 ASSOC_ISCSI_PARENT_TYPE, 87 ASSOC_DD_PARENT_TYPE 88 }; 89 90 /* number of children object type */ 91 const int NUM_OF_CHILD[MAX_OBJ_TYPE] = { 92 0, 93 MAX_ENTITY_CHILD, 94 MAX_ISCSI_CHILD, 95 MAX_PORTAL_CHILD, 96 MAX_PG_CHILD, 97 0, 98 0 99 }; 100 101 /* type of a child object */ 102 const int TYPE_OF_CHILD[MAX_OBJ_TYPE][MAX_CHILD_TYPE] = { 103 { 0, 0 }, 104 { OBJ_ISCSI, OBJ_PORTAL }, 105 { 0, 0 }, 106 { 0, 0 }, 107 { 0, 0 }, 108 { 0, 0 }, 109 { 0, 0 } 110 }; 111 112 /* number of attributes of certain type of object */ 113 const int NUM_OF_ATTRS[MAX_OBJ_TYPE_FOR_SIZE] = { 114 0, 115 NUM_OF_ENTITY_ATTRS, 116 NUM_OF_ISCSI_ATTRS, 117 NUM_OF_PORTAL_ATTRS, 118 NUM_OF_PG_ATTRS, 119 NUM_OF_DD_ATTRS, 120 NUM_OF_DDS_ATTRS, 121 0, /* MAX_OBJ_TYPE */ 122 0, /* OBJ_DUMMY1 */ 123 0, /* OBJ_DUMMY2 */ 124 0, /* OBJ_DUMMY3 */ 125 0, /* OBJ_DUMMY4 */ 126 NUM_OF_ASSOC_ISCSI_ATTRS, 127 NUM_OF_ASSOC_DD_ATTRS 128 }; 129 130 /* the tag of UID of each type of object */ 131 static const int UID_TAG[MAX_OBJ_TYPE_FOR_SIZE] = { 132 0, 133 ISNS_ENTITY_INDEX_ATTR_ID, 134 ISNS_ISCSI_NODE_INDEX_ATTR_ID, 135 ISNS_PORTAL_INDEX_ATTR_ID, 136 ISNS_PG_INDEX_ATTR_ID, 137 ISNS_DD_ID_ATTR_ID, 138 ISNS_DD_SET_ID_ATTR_ID, 139 0, /* MAX_OBJ_TYPE */ 140 0, /* OBJ_DUMMY1 */ 141 0, /* OBJ_DUMMY2 */ 142 0, /* OBJ_DUMMY3 */ 143 0, /* OBJ_DUMMY4 */ 144 ISNS_DD_ISCSI_INDEX_ATTR_ID, 145 ISNS_DD_ID_ATTR_ID 146 }; 147 148 /* the index of UID of each type of object */ 149 const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE] = { 150 0, 151 ATTR_INDEX_ENTITY(ISNS_ENTITY_INDEX_ATTR_ID), 152 ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_INDEX_ATTR_ID), 153 ATTR_INDEX_PORTAL(ISNS_PORTAL_INDEX_ATTR_ID), 154 ATTR_INDEX_PG(ISNS_PG_INDEX_ATTR_ID), 155 ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID), 156 ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID), 157 0, /* MAX_OBJ_TYPE */ 158 0, /* OBJ_DUMMY1 */ 159 0, /* OBJ_DUMMY2 */ 160 0, /* OBJ_DUMMY3 */ 161 0, /* OBJ_DUMMY4 */ 162 ATTR_INDEX_ASSOC_ISCSI(ISNS_DD_ISCSI_INDEX_ATTR_ID), 163 ATTR_INDEX_ASSOC_DD(ISNS_DD_ID_ATTR_ID) 164 }; 165 166 /* the index of the key attributes of each type of object */ 167 static const int KEY_ATTR_INDEX[MAX_OBJ_TYPE][MAX_KEY_ATTRS] = { 168 { 0 }, 169 { ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID), 0 }, 170 { ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID), 171 0 }, 172 { ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID), 173 ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID), 174 0 }, 175 { ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID), 176 ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID), 177 ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID) }, 178 { ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID), 0 }, 179 { ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID), 0 } 180 }; 181 182 /* the operating methods for key attributes of each type of object */ 183 static const int KEY_ATTR_OP[MAX_OBJ_TYPE][MAX_KEY_ATTRS] = { 184 { 0 }, 185 { OP_STRING, 0 }, 186 { OP_STRING, 0 }, 187 { OP_MEMORY_IP6, OP_INTEGER, 0 }, 188 { OP_STRING, OP_MEMORY_IP6, OP_INTEGER }, 189 { OP_STRING, 0 }, 190 { OP_STRING, 0 } 191 }; 192 193 /* the size of each type of object */ 194 static const int SIZEOF_OBJ[MAX_OBJ_TYPE_FOR_SIZE] = { 195 0, 196 sizeof (isns_entity_t), 197 sizeof (isns_iscsi_t), 198 sizeof (isns_portal_t), 199 sizeof (isns_pg_t), 200 sizeof (isns_dd_t), 201 sizeof (isns_dds_t), 202 0, 203 0, 204 0, 205 0, 206 0, 207 sizeof (isns_assoc_iscsi_t), 208 sizeof (isns_assoc_dd_t) 209 }; 210 211 #ifdef DEBUG 212 const int NUM_OF_REF[MAX_OBJ_TYPE_FOR_SIZE] = { 213 #else 214 static const int NUM_OF_REF[MAX_OBJ_TYPE_FOR_SIZE] = { 215 #endif 216 0, 217 0, 218 0, 219 0, 220 PG_REF_COUNT, 221 0, 222 0, 223 0, 224 0, 225 0, 226 0, 227 0, 228 0, 229 0 230 }; 231 232 /* the type of the reference object */ 233 static const int TYPE_OF_REF[MAX_OBJ_TYPE][MAX_REF_COUNT + 1] = { 234 { 0 }, 235 { 0 }, 236 { OBJ_PG, OBJ_PORTAL, 0 }, 237 { OBJ_PG, OBJ_ISCSI, 0 }, 238 { 0, OBJ_ISCSI, OBJ_PORTAL }, 239 { 0 }, 240 { 0 } 241 }; 242 243 /* the operating method for match operation of the reference object */ 244 #define MAX_REF_MATCH (2) 245 static const int REF_MATCH_OPS[MAX_OBJ_TYPE][MAX_REF_MATCH] = { 246 { 0, 0 }, 247 { 0, 0 }, 248 { OP_STRING, 0 }, 249 { OP_MEMORY_IP6, OP_INTEGER }, 250 { 0, 0 }, 251 { 0, 0 }, 252 { 0, 0 } 253 }; 254 255 /* the index of the attribute of being matched object */ 256 static const int REF_MATCH_ID1[MAX_OBJ_TYPE][MAX_REF_MATCH] = { 257 { 0, 0 }, 258 { 0, 0 }, 259 { ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID), 0 }, 260 { ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID), 261 ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID) }, 262 { 0, 0 }, 263 { 0, 0 }, 264 { 0, 0 } 265 }; 266 267 /* the index of the attribute of matching object */ 268 static const int REF_MATCH_ID2[MAX_OBJ_TYPE][MAX_REF_MATCH] = { 269 { 0, 0 }, 270 { 0, 0 }, 271 { ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID), 0 }, 272 { ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID), 273 ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID) }, 274 { 0, 0 }, 275 { 0, 0 }, 276 { 0, 0 } 277 }; 278 279 /* 280 * local functions. 281 */ 282 static uint32_t get_reg_period(); 283 static char *make_unique_name(int *, uint32_t); 284 static lookup_ctrl_t *set_lookup_ctrl(lookup_ctrl_t *, isns_obj_t *); 285 static int setup_ref_lcp(lookup_ctrl_t *, 286 const isns_obj_t *, const isns_obj_t *); 287 static int setup_deref_lcp(lookup_ctrl_t *, 288 const isns_obj_t *, isns_type_t); 289 static int cb_get_parent(void *, void *); 290 static int cb_node_child(void *, void *); 291 static int cb_set_ref(void *, void *); 292 static int cb_clear_ref(void *, void *); 293 static int cb_add_child(void *, void *); 294 static int cb_remove_child(void *, void *); 295 static int cb_verify_ref(void *, void *); 296 static int cb_ref_new2old(void *, void *); 297 static int cb_new_ref(void *, void *); 298 static int ref_new2old( 299 lookup_ctrl_t *, isns_type_t, uint32_t, const isns_obj_t *); 300 static int ref_new2new( 301 lookup_ctrl_t *, const isns_obj_t *, const isns_obj_t *); 302 static int new_ref(const isns_obj_t *, const isns_obj_t *); 303 static uint32_t setup_parent_lcp(lookup_ctrl_t *, isns_obj_t *); 304 static int set_obj_offline(isns_obj_t *); 305 static int copy_attrs(isns_obj_t *, const isns_obj_t *); 306 307 static isns_obj_t *make_default_pg(const isns_obj_t *, const isns_obj_t *); 308 static isns_obj_t *(*const make_ref[MAX_OBJ_TYPE]) 309 (const isns_obj_t *, const isns_obj_t *) = { 310 NULL, 311 NULL, 312 &make_default_pg, 313 &make_default_pg, 314 NULL, 315 NULL, 316 NULL 317 }; 318 319 static uint32_t entity_hval(void *, uint16_t, uint32_t *); 320 static uint32_t iscsi_hval(void *, uint16_t, uint32_t *); 321 static uint32_t portal_hval(void *, uint16_t, uint32_t *); 322 static uint32_t pg_hval(void *, uint16_t, uint32_t *); 323 static uint32_t dd_hval(void *, uint16_t, uint32_t *); 324 static uint32_t dds_hval(void *, uint16_t, uint32_t *); 325 static uint32_t (*const hval_func[MAX_OBJ_TYPE]) 326 (void *, uint16_t, uint32_t *) = { 327 NULL, 328 &entity_hval, 329 &iscsi_hval, 330 &portal_hval, 331 &pg_hval, 332 &dd_hval, 333 &dds_hval 334 }; 335 336 /* 337 * **************************************************************************** 338 * 339 * entity_hval: 340 * caculate the hash value of a network entity object. 341 * 342 * p - the pointer pointers to network entity object or 343 * the lookup control data, both have the key attribute 344 * of a network entity object. 345 * chunk- which chunk of the hash table. 346 * flags- pointer to flags. 347 * return - the hash value. 348 * 349 * **************************************************************************** 350 */ 351 static uint32_t 352 entity_hval( 353 void *p, 354 /* LINTED E_FUNC_ARG_UNUSED */ 355 uint16_t chunk, 356 uint32_t *flags 357 ) 358 { 359 uchar_t *key; 360 isns_obj_t *obj; 361 lookup_ctrl_t *lcp; 362 363 if ((*flags & FLAGS_CTRL_MASK) == 0) { 364 /* p pointers to a network entity object */ 365 obj = (isns_obj_t *)p; 366 key = obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)]. 367 value.ptr; 368 } else { 369 /* p is lookup control data */ 370 lcp = (lookup_ctrl_t *)p; 371 key = lcp->data[0].ptr; 372 } 373 374 return (htab_compute_hval(key)); 375 } 376 377 /* 378 * **************************************************************************** 379 * 380 * iscsi_hval: 381 * caculate the hash value of an iscsi storage node object. 382 * 383 * p - the pointer pointers to iscsi storage node object or 384 * the lookup control data, both have the key attribute 385 * of an iscsi storage node object. 386 * chunk- which chunk of the hash table. 387 * flags- pointer to flags. 388 * return - the hash value. 389 * 390 * **************************************************************************** 391 */ 392 static uint32_t 393 iscsi_hval( 394 void *p, 395 /* LINTED E_FUNC_ARG_UNUSED */ 396 uint16_t chunk, 397 uint32_t *flags 398 ) 399 { 400 uchar_t *key; 401 isns_obj_t *obj; 402 lookup_ctrl_t *lcp; 403 404 if ((*flags & FLAGS_CTRL_MASK) == 0) { 405 /* p pointers to an iscsi storage node object */ 406 obj = (isns_obj_t *)p; 407 key = obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)]. 408 value.ptr; 409 } else { 410 /* p is lookup control data */ 411 lcp = (lookup_ctrl_t *)p; 412 key = lcp->data[0].ptr; 413 } 414 415 return (htab_compute_hval(key)); 416 } 417 418 /* 419 * **************************************************************************** 420 * 421 * portal_hval: 422 * caculate the hash value of a portal object. 423 * 424 * p - the pointer pointers to a portal object or the lookup control 425 * data, both have the key attributes of a portal object. 426 * chunk- which chunk of the hash table. 427 * flags- pointer to flags. 428 * return - the hash value. 429 * 430 * **************************************************************************** 431 */ 432 static uint32_t 433 portal_hval( 434 void *p, 435 /* LINTED E_FUNC_ARG_UNUSED */ 436 uint16_t chunk, 437 uint32_t *flags 438 ) 439 { 440 char buff[INET6_ADDRSTRLEN + 8] = { 0 }; 441 char buff2[8] = { 0 }; 442 uchar_t *key; 443 isns_obj_t *obj; 444 lookup_ctrl_t *lcp; 445 446 in6_addr_t *ip; 447 uint32_t port; 448 449 if ((*flags & FLAGS_CTRL_MASK) == 0) { 450 /* p pointers to a portal object */ 451 obj = (isns_obj_t *)p; 452 ip = obj->attrs[ATTR_INDEX_PORTAL 453 (ISNS_PORTAL_IP_ADDR_ATTR_ID)].value.ip; 454 port = obj->attrs[ATTR_INDEX_PORTAL 455 (ISNS_PORTAL_PORT_ATTR_ID)].value.ui; 456 } else { 457 /* p is lookup control data */ 458 lcp = (lookup_ctrl_t *)p; 459 ip = lcp->data[0].ip; 460 port = lcp->data[1].ui; 461 } 462 463 key = (uchar_t *)inet_ntop(AF_INET6, (void *)ip, 464 buff, sizeof (buff)); 465 (void) snprintf(buff2, sizeof (buff2), "%d", port); 466 (void) strcat((char *)key, buff2); 467 468 return (htab_compute_hval(key)); 469 } 470 471 /* 472 * **************************************************************************** 473 * 474 * pg_hval: 475 * caculate the hash value of a portal group object. 476 * 477 * p - the pointer pointers to a portal group object or the lookup 478 * control data, both have the key attributes of a portal object. 479 * chunk- which chunk of the hash table. 480 * flags- pointer to flags. 481 * return - the hash value. 482 * 483 * **************************************************************************** 484 */ 485 static uint32_t 486 pg_hval( 487 void *p, 488 uint16_t chunk, 489 uint32_t *flags 490 ) 491 { 492 char buff[INET6_ADDRSTRLEN + 8] = { 0 }; 493 char buff2[8] = { 0 }; 494 uchar_t *key = NULL; 495 isns_obj_t *obj; 496 lookup_ctrl_t *lcp; 497 498 in6_addr_t *ip = NULL; 499 uint32_t port; 500 501 if ((*flags & FLAGS_CTRL_MASK) == 0) { 502 /* p is a portal group object */ 503 obj = (isns_obj_t *)p; 504 if (chunk == 0) { 505 /* the first chunk */ 506 key = obj->attrs[ATTR_INDEX_PG 507 (ISNS_PG_ISCSI_NAME_ATTR_ID)].value.ptr; 508 } else { 509 /* another chunk */ 510 ip = obj->attrs[ATTR_INDEX_PG 511 (ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)].value.ip; 512 port = obj->attrs[ATTR_INDEX_PG 513 (ISNS_PG_PORTAL_PORT_ATTR_ID)].value.ui; 514 } 515 } else { 516 /* p is a lookup control data */ 517 lcp = (lookup_ctrl_t *)p; 518 /* clear the chunk flags */ 519 *flags &= ~FLAGS_CHUNK_MASK; 520 if (lcp->op[0] == OP_STRING) { 521 /* the first chunk */ 522 key = lcp->data[0].ptr; 523 } else { 524 /* another chunk */ 525 ip = lcp->data[0].ip; 526 port = lcp->data[1].ui; 527 *flags |= 1; 528 } 529 } 530 531 if (key == NULL) { 532 key = (uchar_t *)inet_ntop(AF_INET6, (void *)ip, 533 buff, sizeof (buff)); 534 (void) snprintf(buff2, sizeof (buff2), "%d", port); 535 (void) strcat((char *)key, buff2); 536 } 537 538 return (htab_compute_hval(key)); 539 } 540 541 /* 542 * **************************************************************************** 543 * 544 * dd_hval: 545 * caculate the hash value of a DD object. 546 * 547 * p - the pointer pointers to a DD object or the lookup control data, 548 * both have the key attributes of a DD object. 549 * chunk- which chunk of the hash table. 550 * flags- pointer to flags. 551 * return - the hash value. 552 * 553 * **************************************************************************** 554 */ 555 static uint32_t 556 dd_hval( 557 void *p, 558 /* LINTED E_FUNC_ARG_UNUSED */ 559 uint16_t chunk, 560 uint32_t *flags 561 ) 562 { 563 uchar_t *key; 564 isns_obj_t *obj; 565 lookup_ctrl_t *lcp; 566 567 if ((*flags & FLAGS_CTRL_MASK) == 0) { 568 /* p is a DD object */ 569 obj = (isns_obj_t *)p; 570 key = obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)]. 571 value.ptr; 572 } else { 573 /* p is a lookup control data */ 574 lcp = (lookup_ctrl_t *)p; 575 key = lcp->data[0].ptr; 576 } 577 578 return (htab_compute_hval(key)); 579 } 580 581 /* 582 * **************************************************************************** 583 * 584 * dds_hval: 585 * caculate the hash value of a DD-set object. 586 * 587 * p - the pointer pointers to a DD-set object or the lookup control data, 588 * both have the key attributes of a DD-set object. 589 * chunk- which chunk of the hash table. 590 * flags- pointer to flags. 591 * return - the hash value. 592 * 593 * **************************************************************************** 594 */ 595 static uint32_t 596 dds_hval( 597 void *p, 598 /* LINTED E_FUNC_ARG_UNUSED */ 599 uint16_t chunk, 600 uint32_t *flags 601 ) 602 { 603 uchar_t *key; 604 isns_obj_t *obj; 605 lookup_ctrl_t *lcp; 606 607 if ((*flags & FLAGS_CTRL_MASK) == 0) { 608 /* p is a DD-set object */ 609 obj = (isns_obj_t *)p; 610 key = obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID)]. 611 value.ptr; 612 } else { 613 /* p is lookup control data */ 614 lcp = (lookup_ctrl_t *)p; 615 key = lcp->data[0].ptr; 616 } 617 618 return (htab_compute_hval(key)); 619 } 620 621 /* 622 * **************************************************************************** 623 * 624 * obj_hval: 625 * caculate the hash value of an object. 626 * 627 * p - the pointer pointers to an object or lookup control data, 628 * both has the object type and the key attributes of an object. 629 * chunk- which chunk of the hash table. 630 * flags- pointer to flags. 631 * return - the hash value. 632 * 633 * **************************************************************************** 634 */ 635 uint32_t 636 obj_hval( 637 void *p, 638 uint16_t chunk, 639 uint32_t *flags 640 ) 641 { 642 isns_type_t type = ((isns_obj_t *)p)->type; 643 644 return (hval_func[type](p, chunk, flags)); 645 } 646 647 /* 648 * **************************************************************************** 649 * 650 * get_obj_uid: 651 * get the UID of an object. 652 * 653 * p - the pointer pointers to an object. 654 * return - the UID. 655 * 656 * **************************************************************************** 657 */ 658 uint32_t 659 get_obj_uid( 660 const void *p 661 ) 662 { 663 isns_obj_t *obj = (isns_obj_t *)p; 664 isns_attr_t *attr = &obj->attrs[UID_ATTR_INDEX[obj->type]]; 665 uint32_t uid = attr->value.ui; 666 return (uid); 667 } 668 669 /* 670 * **************************************************************************** 671 * 672 * set_obj_uid: 673 * set the UID of an object. 674 * 675 * p - the pointer pointers to an object. 676 * uid - the UID. 677 * return - the UID. 678 * 679 * **************************************************************************** 680 */ 681 uint32_t 682 set_obj_uid( 683 void *p, 684 uint32_t uid 685 ) 686 { 687 isns_obj_t *obj = (isns_obj_t *)p; 688 isns_attr_t *attr = &obj->attrs[UID_ATTR_INDEX[obj->type]]; 689 690 /* set the tag, len and value */ 691 attr->tag = UID_TAG[obj->type]; 692 attr->len = 4; 693 attr->value.ui = uid; 694 695 return (uid); 696 } 697 698 /* 699 * **************************************************************************** 700 * 701 * obj_cmp: 702 * compare between two objects or an object with a lookup control data. 703 * 704 * p1 - the pointer points to an object. 705 * p2 - the pointer points to an object or a lookup control data. 706 * flags- 0: p2 is an object; otherwise p2 is a lookup control data. 707 * return - the comparsion result. 708 * 709 * **************************************************************************** 710 */ 711 int 712 obj_cmp( 713 void *p1, 714 void *p2, 715 int flags 716 ) 717 { 718 isns_obj_t *obj = (isns_obj_t *)p1; 719 lookup_ctrl_t buff = { 0 }; 720 lookup_ctrl_t *lcp; 721 uint32_t uid; 722 723 if (flags == 0) { 724 lcp = set_lookup_ctrl(&buff, (isns_obj_t *)p2); 725 } else { 726 lcp = (lookup_ctrl_t *)p2; 727 uid = get_obj_uid(obj); 728 /* the object are linked with decending order by */ 729 /* the object UID, if the object UID is greater than */ 730 /* or equal to the current UID, it needs to compare */ 731 /* for the next one. */ 732 if (lcp->curr_uid != 0 && uid >= lcp->curr_uid) { 733 return (-1); 734 } 735 } 736 737 return (key_cmp(lcp, obj)); 738 } 739 740 /* 741 * **************************************************************************** 742 * 743 * replace_object: 744 * replace an existing object with the new one. 745 * 746 * p1 - the pointer points to an object being replaced. 747 * p2 - the pointer points to a new object. 748 * uid_p- points to uid for returning. 749 * flag - 0: do not free the source object, otherwise free it. 750 * return - error code. 751 * 752 * **************************************************************************** 753 */ 754 int 755 replace_object( 756 void *p1, 757 void *p2, 758 uint32_t *uid_p, 759 int flag 760 ) 761 { 762 int ec = 0; 763 764 #ifndef SKIP_SRC_AUTH 765 uint32_t *pp_dst, *pp_src, swap; 766 #endif 767 int online; 768 769 isns_obj_t *dst = (isns_obj_t *)p1; 770 isns_obj_t *src = (isns_obj_t *)p2; 771 772 if (src->type == OBJ_DD || src->type == OBJ_DDS) { 773 /* replace not allowed */ 774 return (ERR_NAME_IN_USE); 775 } 776 777 online = is_obj_online(dst); 778 779 /* set cache update flag */ 780 SET_CACHE_UPDATED(); 781 782 /* update parent uid */ 783 #ifndef SKIP_SRC_AUTH 784 pp_dst = get_parent_p(dst); 785 if (pp_dst != NULL) { 786 pp_src = get_parent_p(src); 787 swap = *pp_dst; 788 *pp_dst = *pp_src; 789 if (swap != 0) { 790 *pp_src = swap; 791 } 792 } 793 #endif 794 795 /* update all of attributes */ 796 if (copy_attrs(dst, src) != 0) { 797 return (ISNS_RSP_INTERNAL_ERROR); 798 } 799 800 /* free up the src object */ 801 if (flag != 0) { 802 (void) free_object(src); 803 } else if (online == 0) { 804 (void) set_obj_uid(src, get_obj_uid(dst)); 805 (void) set_obj_offline(src); 806 } 807 808 /* update data store */ 809 if (sys_q != NULL) { 810 ec = write_data(DATA_UPDATE, dst); 811 } else { 812 /* we should never have duplicated entry in data store */ 813 ec = ISNS_RSP_INTERNAL_ERROR; 814 } 815 816 /* trigger a scn */ 817 if (ec == 0) { 818 if (scn_q != NULL) { 819 (void) make_scn((online == 0) ? 820 ISNS_OBJECT_ADDED : 821 ISNS_OBJECT_UPDATED, 822 dst); 823 } 824 if (uid_p != NULL) { 825 *uid_p = get_obj_uid(dst); 826 } 827 } 828 829 return (ec); 830 } 831 832 /* 833 * **************************************************************************** 834 * 835 * add_object: 836 * post function after adding a new object. 837 * 838 * p - object which has been added. 839 * return - error code. 840 * 841 * **************************************************************************** 842 */ 843 int 844 add_object( 845 void *p 846 ) 847 { 848 int ec = 0; 849 850 isns_obj_t *obj = (isns_obj_t *)p; 851 852 /* add the new object to data store */ 853 if (sys_q != NULL) { 854 ec = write_data(DATA_ADD, obj); 855 } 856 857 /* trigger a scn */ 858 if (ec == 0 && scn_q != NULL) { 859 (void) make_scn(ISNS_OBJECT_ADDED, obj); 860 } 861 862 return (ec); 863 } 864 865 /* 866 * **************************************************************************** 867 * 868 * obj_tab_init: 869 * initialize the object hash tables. 870 * 871 * c - points to the cache. 872 * return - error code. 873 * 874 * **************************************************************************** 875 */ 876 int 877 obj_tab_init( 878 struct cache *c 879 ) 880 { 881 htab_t *t; 882 883 htab_init(); 884 885 /* 886 * allocate an array of pointer for the object hash tables. 887 */ 888 c->t = (struct htab **)calloc(sizeof (struct htab *), MAX_OBJ_TYPE); 889 if (c->t == NULL) { 890 return (1); 891 } 892 893 /* 894 * hash table for network entity objects. 895 */ 896 t = htab_create(UID_FLAGS_SEQ, 8, 1); 897 if (t != NULL) { 898 t->c = c; 899 c->t[OBJ_ENTITY] = t; 900 } else { 901 return (1); 902 } 903 904 /* 905 * hash table for iscsi storage node objects. 906 */ 907 t = htab_create(UID_FLAGS_SEQ, 8, 1); 908 if (t != NULL) { 909 t->c = c; 910 c->t[OBJ_ISCSI] = t; 911 } else { 912 return (1); 913 } 914 915 /* 916 * hash table for portal objects. 917 */ 918 t = htab_create(UID_FLAGS_SEQ, 8, 1); 919 if (t != NULL) { 920 t->c = c; 921 c->t[OBJ_PORTAL] = t; 922 } else { 923 return (1); 924 } 925 926 /* 927 * hash table for portal group objects. 928 */ 929 t = htab_create(UID_FLAGS_SEQ, 8, 2); 930 if (t != NULL) { 931 t->c = c; 932 c->t[OBJ_PG] = t; 933 } else { 934 return (1); 935 } 936 937 /* 938 * hash table for discovery domain objects. 939 */ 940 t = htab_create(0, 6, 1); 941 if (t != NULL) { 942 t->c = c; 943 c->t[OBJ_DD] = t; 944 } else { 945 return (1); 946 } 947 948 /* 949 * hash table for discovery domain set objects. 950 */ 951 t = htab_create(0, 4, 1); 952 if (t != NULL) { 953 t->c = c; 954 c->t[OBJ_DDS] = t; 955 } else { 956 return (1); 957 } 958 959 return (0); 960 } 961 962 /* 963 * **************************************************************************** 964 * 965 * get_ref_np: 966 * get the ref pointer of the portal group object. 967 * 968 * obj - portal group object. 969 * return - ref pointer. 970 * 971 * **************************************************************************** 972 */ 973 static uint32_t * 974 get_ref_np( 975 isns_obj_t *obj, 976 int n 977 ) 978 { 979 uint32_t *refp = 980 obj->type == OBJ_PG ? &((isns_pg_t *)obj)->ref[n] : NULL; 981 982 return (refp); 983 } 984 985 #ifdef DEBUG 986 uint32_t 987 #else 988 static uint32_t 989 #endif 990 get_ref_n( 991 isns_obj_t *obj, 992 int n 993 ) 994 { 995 return (*get_ref_np(obj, n)); 996 } 997 998 static uint32_t * 999 get_ref_p( 1000 isns_obj_t *obj, 1001 isns_type_t rt 1002 ) 1003 { 1004 isns_type_t t = obj->type; 1005 1006 int i = 0; 1007 while (i < NUM_OF_REF[t]) { 1008 if (rt == TYPE_OF_REF[t][i + 1]) { 1009 return (get_ref_np(obj, i)); 1010 } 1011 i ++; 1012 } 1013 1014 return (NULL); 1015 } 1016 1017 uint32_t 1018 get_ref_t( 1019 isns_obj_t *obj, 1020 isns_type_t type 1021 ) 1022 { 1023 uint32_t *refp = get_ref_p(obj, type); 1024 1025 if (refp != NULL) { 1026 return (*refp); 1027 /* LINTED E_NOP_ELSE_STMT */ 1028 } else { 1029 ASSERT(0); 1030 } 1031 1032 return (0); 1033 } 1034 1035 /* 1036 * **************************************************************************** 1037 * 1038 * get_parent_p: 1039 * get the pointer of the parent object. 1040 * 1041 * obj - an object. 1042 * return - parent object pointer. 1043 * 1044 * **************************************************************************** 1045 */ 1046 uint32_t *const 1047 get_parent_p( 1048 const isns_obj_t *obj 1049 ) 1050 { 1051 uint32_t *pp; 1052 switch (obj->type) { 1053 case OBJ_ISCSI: 1054 pp = &((isns_iscsi_t *)obj)->puid; 1055 break; 1056 case OBJ_PORTAL: 1057 pp = &((isns_portal_t *)obj)->puid; 1058 break; 1059 case OBJ_PG: 1060 pp = &((isns_pg_t *)obj)->puid; 1061 break; 1062 case OBJ_ASSOC_ISCSI: 1063 pp = &((isns_assoc_iscsi_t *)obj)->puid; 1064 break; 1065 case OBJ_ASSOC_DD: 1066 pp = &((isns_assoc_dd_t *)obj)->puid; 1067 break; 1068 default: 1069 pp = NULL; 1070 break; 1071 } 1072 1073 return (pp); 1074 } 1075 1076 uint32_t 1077 get_parent_uid( 1078 const isns_obj_t *obj 1079 ) 1080 { 1081 uint32_t *pp = get_parent_p(obj); 1082 if (pp != NULL) { 1083 return (*pp); 1084 } 1085 1086 return (0); 1087 } 1088 1089 /* 1090 * **************************************************************************** 1091 * 1092 * get_child_np: 1093 * get the pointer of the UID array of the n'th child of an object. 1094 * 1095 * obj - an object. 1096 * n - the child index. 1097 * return - the pointer of the UID array. 1098 * 1099 * **************************************************************************** 1100 */ 1101 static uint32_t ** 1102 get_child_np( 1103 isns_obj_t *obj, 1104 int n 1105 ) 1106 { 1107 uint32_t **pp = 1108 obj->type == OBJ_ENTITY ? &((isns_entity_t *)obj)->cuid[n] : NULL; 1109 1110 return (pp); 1111 } 1112 1113 /* 1114 * **************************************************************************** 1115 * 1116 * get_child_n: 1117 * get the UID array of the n'th child of an object. 1118 * 1119 * obj - an object. 1120 * n - the child index. 1121 * return - the UID array. 1122 * 1123 * **************************************************************************** 1124 */ 1125 #ifdef DEBUG 1126 uint32_t * 1127 #else 1128 static uint32_t * 1129 #endif 1130 get_child_n( 1131 isns_obj_t *obj, 1132 int n 1133 ) 1134 { 1135 uint32_t **pp = get_child_np(obj, n); 1136 1137 if (pp != NULL) { 1138 return (*pp); 1139 } 1140 1141 ASSERT(0); 1142 return (NULL); 1143 } 1144 1145 /* 1146 * **************************************************************************** 1147 * 1148 * get_child_p: 1149 * get the pointer of the UID array of the child matching the type. 1150 * 1151 * base - an object. 1152 * child_type - the child object type. 1153 * return - the pointer of the UID array. 1154 * 1155 * **************************************************************************** 1156 */ 1157 static uint32_t ** 1158 get_child_p( 1159 isns_obj_t *base, 1160 int child_type 1161 ) 1162 { 1163 uint32_t **pp = NULL; 1164 int i = 0; 1165 while (i < NUM_OF_CHILD[base->type]) { 1166 if (child_type == TYPE_OF_CHILD[base->type][i]) { 1167 pp = get_child_np(base, i); 1168 break; 1169 } 1170 i ++; 1171 } 1172 1173 return (pp); 1174 } 1175 1176 /* 1177 * **************************************************************************** 1178 * 1179 * get_child_t: 1180 * get the UID array of the child object matching the type. 1181 * 1182 * base - an object. 1183 * child_type - the child object type. 1184 * return - the UID array. 1185 * 1186 * **************************************************************************** 1187 */ 1188 uint32_t * 1189 get_child_t( 1190 isns_obj_t *base, 1191 int child_type 1192 ) 1193 { 1194 uint32_t **pp = get_child_p(base, child_type); 1195 1196 if (pp != NULL) { 1197 return (*pp); 1198 } else { 1199 return (NULL); 1200 } 1201 } 1202 1203 /* 1204 * **************************************************************************** 1205 * 1206 * key_cmp: 1207 * compare the object against the lookup control data. 1208 * 1209 * lcp - the lookup control data. 1210 * obj - an object. 1211 * return - comparison result. 1212 * 1213 * **************************************************************************** 1214 */ 1215 int 1216 key_cmp( 1217 lookup_ctrl_t *lcp, 1218 isns_obj_t *obj 1219 ) 1220 { 1221 int i = 0; 1222 int match = 1; 1223 while (i < MAX_LOOKUP_CTRL && lcp->op[i] > 0 && match) { 1224 isns_attr_t *attr = &obj->attrs[lcp->id[i]]; 1225 switch (lcp->op[i]) { 1226 case OP_STRING: 1227 match = (strcmp((const char *)lcp->data[i].ptr, 1228 (const char *)attr->value.ptr) == 0); 1229 break; 1230 case OP_INTEGER: 1231 match = (lcp->data[i].ui == attr->value.ui); 1232 break; 1233 case OP_MEMORY_IP6: 1234 match = !memcmp((void *)lcp->data[i].ip, 1235 (void *)attr->value.ip, 1236 sizeof (in6_addr_t)); 1237 break; 1238 default: 1239 ASSERT(0); 1240 match = 0; 1241 break; 1242 } 1243 i ++; 1244 } 1245 1246 if (i && match) { 1247 return (0); 1248 } else { 1249 return (1); 1250 } 1251 } 1252 1253 /* 1254 * **************************************************************************** 1255 * 1256 * set_lookup_ctrl: 1257 * fill in the lookup control data for an object. 1258 * 1259 * lcp - the lookup control data. 1260 * obj - an object. 1261 * return - the lookup control data. 1262 * 1263 * **************************************************************************** 1264 */ 1265 static lookup_ctrl_t * 1266 set_lookup_ctrl( 1267 lookup_ctrl_t *lcp, 1268 isns_obj_t *obj 1269 ) 1270 { 1271 isns_type_t type = obj->type; 1272 uint32_t id, op; 1273 int i = 0; 1274 1275 lcp->type = type; 1276 while (i < MAX_KEY_ATTRS) { 1277 op = KEY_ATTR_OP[type][i]; 1278 if (op != 0) { 1279 id = KEY_ATTR_INDEX[type][i]; 1280 lcp->id[i] = id; 1281 lcp->op[i] = op; 1282 lcp->data[i].ui = obj->attrs[id].value.ui; 1283 } else { 1284 break; 1285 } 1286 i ++; 1287 } 1288 1289 return (lcp); 1290 } 1291 1292 /* 1293 * **************************************************************************** 1294 * 1295 * assign_attr: 1296 * assign an attribute. 1297 * 1298 * attr - the attribute being assigned. 1299 * tmp - the attribute. 1300 * return - error code. 1301 * 1302 * **************************************************************************** 1303 */ 1304 int 1305 assign_attr( 1306 isns_attr_t *attr, 1307 const isns_attr_t *tmp 1308 ) 1309 { 1310 uint32_t t; 1311 1312 switch (tmp->tag) { 1313 case ISNS_EID_ATTR_ID: 1314 case ISNS_DD_SET_NAME_ATTR_ID: 1315 case ISNS_DD_NAME_ATTR_ID: 1316 if (tmp->len == 0 && attr->len == 0) { 1317 int len; 1318 char *name = make_unique_name(&len, tmp->tag); 1319 if (name != NULL) { 1320 attr->value.ptr = (uchar_t *)name; 1321 attr->tag = tmp->tag; 1322 attr->len = len; 1323 } else { 1324 /* memory exhausted */ 1325 return (1); 1326 } 1327 } 1328 case ISNS_PORTAL_NAME_ATTR_ID: 1329 case ISNS_ISCSI_NAME_ATTR_ID: 1330 case ISNS_ISCSI_ALIAS_ATTR_ID: 1331 case ISNS_ISCSI_AUTH_METHOD_ATTR_ID: 1332 case ISNS_PG_ISCSI_NAME_ATTR_ID: 1333 case ISNS_DD_ISCSI_NAME_ATTR_ID: 1334 if (tmp->len == 0) { 1335 return (0); 1336 } else if (tmp->len >= attr->len) { 1337 attr->value.ptr = realloc( 1338 attr->value.ptr, tmp->len + 1); 1339 } 1340 if (attr->value.ptr != NULL) { 1341 (void) strncpy((char *)attr->value.ptr, 1342 (char *)tmp->value.ptr, tmp->len); 1343 attr->value.ptr[tmp->len] = 0; 1344 attr->tag = tmp->tag; 1345 attr->len = tmp->len; 1346 } else { 1347 /* memory exhausted */ 1348 return (1); 1349 } 1350 break; 1351 case ISNS_MGMT_IP_ADDR_ATTR_ID: 1352 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1353 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 1354 if (attr->value.ip == NULL) { 1355 attr->value.ip = (in6_addr_t *)calloc(1, tmp->len); 1356 } 1357 if (attr->value.ip != NULL) { 1358 (void) memcpy((void *)attr->value.ip, 1359 (void *)tmp->value.ip, tmp->len); 1360 attr->tag = tmp->tag; 1361 attr->len = tmp->len; 1362 } else { 1363 /* memory exhausted */ 1364 return (1); 1365 } 1366 break; 1367 case ISNS_ENTITY_INDEX_ATTR_ID: 1368 case ISNS_PORTAL_INDEX_ATTR_ID: 1369 case ISNS_ISCSI_NODE_INDEX_ATTR_ID: 1370 case ISNS_PG_INDEX_ATTR_ID: 1371 case ISNS_DD_SET_ID_ATTR_ID: 1372 case ISNS_DD_ID_ATTR_ID: 1373 if (attr->value.ui != 0) { 1374 break; 1375 } 1376 case ISNS_ENTITY_PROTOCOL_ATTR_ID: 1377 case ISNS_VERSION_RANGE_ATTR_ID: 1378 1379 case ISNS_PORTAL_PORT_ATTR_ID: 1380 case ISNS_ESI_PORT_ATTR_ID: 1381 case ISNS_SCN_PORT_ATTR_ID: 1382 1383 case ISNS_ISCSI_NODE_TYPE_ATTR_ID: 1384 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 1385 1386 case ISNS_PG_PORTAL_PORT_ATTR_ID: 1387 case ISNS_PG_TAG_ATTR_ID: 1388 1389 case ISNS_DD_SET_STATUS_ATTR_ID: 1390 case ISNS_DD_ISCSI_INDEX_ATTR_ID: 1391 attr->tag = tmp->tag; 1392 attr->len = tmp->len; 1393 attr->value.ui = tmp->value.ui; 1394 break; 1395 case ISNS_ENTITY_REG_PERIOD_ATTR_ID: 1396 attr->tag = tmp->tag; 1397 attr->len = tmp->len; 1398 attr->value.ui = tmp->value.ui; 1399 t = get_reg_period(); 1400 if (attr->value.ui > t) { 1401 attr->value.ui = t; 1402 } else if (attr->value.ui < ONE_DAY) { 1403 attr->value.ui = ONE_DAY; 1404 } 1405 break; 1406 case ISNS_ESI_INTERVAL_ATTR_ID: 1407 attr->tag = tmp->tag; 1408 attr->len = tmp->len; 1409 attr->value.ui = tmp->value.ui; 1410 if (attr->value.ui > ONE_DAY) { 1411 attr->value.ui = ONE_DAY; 1412 } else if (attr->value.ui < MIN_ESI_INTVAL) { 1413 attr->value.ui = MIN_ESI_INTVAL; /* 20 seconds */ 1414 } 1415 break; 1416 default: 1417 ASSERT(0); 1418 /* don't assign the attribute */ 1419 break; 1420 } 1421 return (0); 1422 } 1423 1424 /* 1425 * **************************************************************************** 1426 * 1427 * copy_attrs: 1428 * copy all of attributes from one object to another. 1429 * 1430 * dst - the destination object. 1431 * tmp - the source object. 1432 * return - error code. 1433 * 1434 * **************************************************************************** 1435 */ 1436 static int 1437 copy_attrs( 1438 isns_obj_t *dst, 1439 const isns_obj_t *src 1440 ) 1441 { 1442 int i = 0; 1443 int n = NUM_OF_ATTRS[dst->type]; 1444 1445 isns_attr_t *dst_attr; 1446 const isns_attr_t *src_attr; 1447 1448 while (i < n) { 1449 src_attr = &(src->attrs[i]); 1450 if (src_attr->tag != 0) { 1451 dst_attr = &(dst->attrs[i]); 1452 if (assign_attr(dst_attr, src_attr) != 0) { 1453 return (1); 1454 } 1455 } 1456 i ++; 1457 } 1458 1459 return (0); 1460 } 1461 1462 /* 1463 * **************************************************************************** 1464 * 1465 * extract_attr: 1466 * extract an attribute from a TLV format data. 1467 * 1468 * attr - the attribute. 1469 * tlv - the TLV format data. 1470 * return - error code. 1471 * 1472 * **************************************************************************** 1473 */ 1474 int 1475 extract_attr( 1476 isns_attr_t *attr, 1477 const isns_tlv_t *tlv, 1478 int flag 1479 ) 1480 { 1481 int ec = 0; 1482 1483 uint32_t min_len = 4, max_len = 224; 1484 1485 switch (tlv->attr_id) { 1486 case ISNS_EID_ATTR_ID: 1487 min_len = 0; 1488 case ISNS_PORTAL_NAME_ATTR_ID: 1489 case ISNS_ISCSI_ALIAS_ATTR_ID: 1490 case ISNS_DD_SET_NAME_ATTR_ID: 1491 case ISNS_DD_NAME_ATTR_ID: 1492 max_len = 256; 1493 case ISNS_ISCSI_NAME_ATTR_ID: 1494 case ISNS_PG_ISCSI_NAME_ATTR_ID: 1495 if (tlv->attr_len < min_len || tlv->attr_len > max_len) { 1496 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1497 } else { 1498 attr->tag = tlv->attr_id; 1499 attr->len = tlv->attr_len; 1500 attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]); 1501 } 1502 break; 1503 case ISNS_ISCSI_AUTH_METHOD_ATTR_ID: 1504 attr->tag = tlv->attr_id; 1505 attr->len = tlv->attr_len; 1506 attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]); 1507 break; 1508 case ISNS_MGMT_IP_ADDR_ATTR_ID: 1509 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1510 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 1511 if (tlv->attr_len != 16) { 1512 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1513 } else { 1514 attr->tag = tlv->attr_id; 1515 attr->len = tlv->attr_len; 1516 attr->value.ip = (void *)&(tlv->attr_value[0]); 1517 } 1518 break; 1519 case ISNS_ENTITY_PROTOCOL_ATTR_ID: 1520 case ISNS_VERSION_RANGE_ATTR_ID: 1521 case ISNS_ENTITY_REG_PERIOD_ATTR_ID: 1522 /* fall throught */ 1523 case ISNS_PORTAL_PORT_ATTR_ID: 1524 case ISNS_ESI_INTERVAL_ATTR_ID: 1525 case ISNS_ESI_PORT_ATTR_ID: 1526 case ISNS_SCN_PORT_ATTR_ID: 1527 /* fall throught */ 1528 case ISNS_ISCSI_NODE_TYPE_ATTR_ID: 1529 /* fall throught */ 1530 case ISNS_PG_PORTAL_PORT_ATTR_ID: 1531 /* fall throught */ 1532 case ISNS_DD_SET_ID_ATTR_ID: 1533 case ISNS_DD_SET_STATUS_ATTR_ID: 1534 /* fall throught */ 1535 case ISNS_DD_ID_ATTR_ID: 1536 if (tlv->attr_len != 4) { 1537 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1538 break; 1539 } 1540 case ISNS_PG_TAG_ATTR_ID: 1541 attr->tag = tlv->attr_id; 1542 attr->len = tlv->attr_len; 1543 if (tlv->attr_len == 4) { 1544 attr->value.ui = ntohl(*(uint32_t *) 1545 &(tlv->attr_value[0])); 1546 } else { 1547 attr->value.ui = 0; 1548 } 1549 break; 1550 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 1551 /* ignore scn bitmap attribute during object registration, */ 1552 /* it is registered by scn_reg message. */ 1553 case ISNS_ENTITY_ISAKMP_P1_ATTR_ID: 1554 case ISNS_ENTITY_CERT_ATTR_ID: 1555 case ISNS_PORTAL_SEC_BMP_ATTR_ID: 1556 case ISNS_PORTAL_ISAKMP_P1_ATTR_ID: 1557 case ISNS_PORTAL_ISAKMP_P2_ATTR_ID: 1558 case ISNS_PORTAL_CERT_ATTR_ID: 1559 break; 1560 case ISNS_PORTAL_INDEX_ATTR_ID: 1561 case ISNS_ISCSI_NODE_INDEX_ATTR_ID: 1562 case ISNS_PG_INDEX_ATTR_ID: 1563 if (flag == 0) { 1564 if (tlv->attr_len != 4) { 1565 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1566 } else { 1567 attr->tag = tlv->attr_id; 1568 attr->len = tlv->attr_len; 1569 attr->value.ui = ntohl(*(uint32_t *) 1570 &(tlv->attr_value[0])); 1571 } 1572 break; 1573 } 1574 case ISNS_ENTITY_INDEX_ATTR_ID: 1575 case ISNS_TIMESTAMP_ATTR_ID: 1576 default: 1577 if (flag == 0) { 1578 ec = ISNS_RSP_INVALID_QRY; 1579 } else { 1580 ec = ISNS_RSP_INVALID_REGIS; 1581 } 1582 break; 1583 } 1584 1585 return (ec); 1586 } 1587 1588 /* 1589 * **************************************************************************** 1590 * 1591 * copy_attr: 1592 * copy an attribute from a TLV format data. 1593 * 1594 * attr - the attribute. 1595 * tlv - the TLV format data. 1596 * return - error code. 1597 * 1598 * **************************************************************************** 1599 */ 1600 static int 1601 copy_attr( 1602 isns_attr_t *attr, 1603 const isns_tlv_t *tlv 1604 ) 1605 { 1606 int ec = 0; 1607 1608 isns_attr_t tmp = { 0 }; 1609 1610 /* extract the attribute first */ 1611 ec = extract_attr(&tmp, tlv, 1); 1612 1613 /* assign the attribute */ 1614 if (ec == 0 && tmp.tag != 0) { 1615 if (assign_attr(attr, &tmp) != 0) { 1616 ec = ISNS_RSP_INTERNAL_ERROR; 1617 } 1618 } 1619 1620 return (ec); 1621 } 1622 1623 /* 1624 * **************************************************************************** 1625 * 1626 * get_timestamp: 1627 * get current timestamp. 1628 * 1629 * return - current timestamp. 1630 * 1631 * **************************************************************************** 1632 */ 1633 uint32_t 1634 get_timestamp( 1635 ) 1636 { 1637 uint32_t t; 1638 int flag; 1639 1640 /* block the scheduler */ 1641 (void) pthread_mutex_lock(&el_mtx); 1642 1643 /* get most current time */ 1644 if (sys_q != NULL) { 1645 /* need to wakeup idle */ 1646 flag = 1; 1647 } else { 1648 flag = 0; 1649 } 1650 t = get_stopwatch(flag); 1651 1652 /* unblock it */ 1653 (void) pthread_mutex_unlock(&el_mtx); 1654 1655 return (t); 1656 } 1657 1658 /* 1659 * **************************************************************************** 1660 * 1661 * get_reg_period: 1662 * get the longest registration period. 1663 * 1664 * return - the longest registration period. 1665 * 1666 * **************************************************************************** 1667 */ 1668 static uint32_t 1669 get_reg_period( 1670 ) 1671 { 1672 uint32_t t; 1673 uint32_t period; 1674 1675 /* get most current time */ 1676 t = get_timestamp(); 1677 1678 /* just one second before the end of the world */ 1679 period = INFINITY - t - 1; 1680 1681 return (period); 1682 } 1683 1684 /* 1685 * **************************************************************************** 1686 * 1687 * obj_calloc: 1688 * allocate memory space for an object. 1689 * 1690 * type - the object type. 1691 * return - pointer of the object being allocated. 1692 * 1693 * **************************************************************************** 1694 */ 1695 isns_obj_t * 1696 obj_calloc( 1697 int type 1698 ) 1699 { 1700 isns_obj_t *obj = NULL; 1701 1702 obj = (isns_obj_t *)calloc(1, SIZEOF_OBJ[type]); 1703 if (obj != NULL) { 1704 obj->type = type; 1705 #ifdef DEBUG 1706 if (verbose_mc) { 1707 printf("object(%d) allocated\n", type); 1708 } 1709 #endif 1710 } 1711 1712 return (obj); 1713 } 1714 1715 /* 1716 * **************************************************************************** 1717 * 1718 * make_default_entity: 1719 * generate a default network entity object. 1720 * 1721 * return - pointer of the default network entity object. 1722 * 1723 * **************************************************************************** 1724 */ 1725 isns_obj_t * 1726 make_default_entity( 1727 ) 1728 { 1729 uint32_t t; 1730 1731 isns_obj_t *obj = obj_calloc(OBJ_ENTITY); 1732 isns_attr_t *attr; 1733 if (obj != NULL) { 1734 int len; 1735 char *eid = make_unique_name(&len, ISNS_EID_ATTR_ID); 1736 if (!eid) { 1737 free(obj); 1738 return (NULL); 1739 } 1740 attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)]; 1741 1742 /* set default entity name */ 1743 attr->tag = ISNS_EID_ATTR_ID; 1744 attr->len = len; 1745 attr->value.ptr = (uchar_t *)eid; 1746 1747 /* set default registration period */ 1748 attr = &obj->attrs[ 1749 ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)]; 1750 if (attr->tag == 0) { 1751 attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID; 1752 attr->len = 4; 1753 t = get_reg_period(); 1754 attr->value.ui = t; 1755 } 1756 } 1757 1758 return (obj); 1759 } 1760 1761 /* 1762 * **************************************************************************** 1763 * 1764 * make_default_pg: 1765 * generate a default portal group object. 1766 * 1767 * iscsi - the iscsi storage node object. 1768 * portal - the portal object. 1769 * return - pointer of the default portal group object. 1770 * 1771 * **************************************************************************** 1772 */ 1773 static isns_obj_t * 1774 make_default_pg( 1775 const isns_obj_t *p1, 1776 const isns_obj_t *p2 1777 ) 1778 { 1779 const isns_obj_t *iscsi, *portal; 1780 const isns_attr_t *name, *addr, *port; 1781 isns_obj_t *pg; 1782 1783 uchar_t *pg_name; 1784 in6_addr_t *pg_addr; 1785 1786 isns_attr_t *attr; 1787 1788 uint32_t *refp; 1789 1790 if (p1->type == OBJ_ISCSI) { 1791 iscsi = p1; 1792 portal = p2; 1793 } else { 1794 iscsi = p2; 1795 portal = p1; 1796 } 1797 name = &iscsi->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)]; 1798 addr = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)]; 1799 port = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)]; 1800 1801 pg = obj_calloc(OBJ_PG); 1802 pg_name = (uchar_t *)malloc(name->len); 1803 pg_addr = (in6_addr_t *)malloc(addr->len); 1804 if (pg != NULL && pg_name != NULL && pg_addr != NULL) { 1805 (void) strcpy((char *)pg_name, (char *)name->value.ptr); 1806 attr = &pg->attrs[ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID)]; 1807 attr->tag = ISNS_PG_ISCSI_NAME_ATTR_ID; 1808 attr->len = name->len; 1809 attr->value.ptr = pg_name; 1810 1811 (void) memcpy((void *)pg_addr, 1812 (void *)addr->value.ip, addr->len); 1813 attr = &pg->attrs[ATTR_INDEX_PG( 1814 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)]; 1815 attr->tag = ISNS_PG_PORTAL_IP_ADDR_ATTR_ID; 1816 attr->len = addr->len; 1817 attr->value.ip = pg_addr; 1818 1819 attr = &pg->attrs[ATTR_INDEX_PG( 1820 ISNS_PG_PORTAL_PORT_ATTR_ID)]; 1821 attr->tag = ISNS_PG_PORTAL_PORT_ATTR_ID; 1822 attr->len = port->len; 1823 attr->value.ui = port->value.ui; 1824 1825 attr = &pg->attrs[ATTR_INDEX_PG( 1826 ISNS_PG_TAG_ATTR_ID)]; 1827 attr->tag = ISNS_PG_TAG_ATTR_ID; 1828 attr->len = 4; 1829 attr->value.ui = ISNS_DEFAULT_PGT; 1830 1831 refp = get_ref_p(pg, OBJ_ISCSI); 1832 *refp = get_obj_uid(iscsi); 1833 1834 refp = get_ref_p(pg, OBJ_PORTAL); 1835 *refp = get_obj_uid(portal); 1836 1837 (void) set_parent_obj(pg, get_parent_uid(iscsi)); 1838 } else { 1839 free(pg); 1840 free(pg_name); 1841 free(pg_addr); 1842 pg = NULL; 1843 } 1844 1845 return (pg); 1846 } 1847 1848 /* 1849 * **************************************************************************** 1850 * 1851 * reg_get_entity: 1852 * parse the Operating Attributes of the DevAttrReg message and 1853 * create the Network Entity object if it has one. 1854 * 1855 * p - the pointer of the object for returning. 1856 * op - the operating attributes. 1857 * op_len - the length of the operating attributes. 1858 * return - error code. 1859 * 1860 * **************************************************************************** 1861 */ 1862 int 1863 reg_get_entity( 1864 isns_obj_t **p, 1865 isns_tlv_t **op, 1866 uint16_t *op_len 1867 ) 1868 { 1869 int ec = 0; 1870 1871 isns_tlv_t *tmp; 1872 uint16_t tmp_len; 1873 isns_attr_t *attr; 1874 1875 isns_obj_t *entity = NULL; 1876 1877 tmp = *op; 1878 tmp_len = *op_len; 1879 1880 /* parse the entity object */ 1881 if (tmp_len >= 8 && IS_ENTITY_KEY(tmp->attr_id)) { 1882 entity = obj_calloc(OBJ_ENTITY); 1883 if (entity != NULL) { 1884 do { 1885 attr = &entity->attrs[ 1886 ATTR_INDEX_ENTITY(tmp->attr_id)]; 1887 ec = copy_attr(attr, tmp); 1888 NEXT_TLV(tmp, tmp_len); 1889 } while (ec == 0 && 1890 tmp_len >= 8 && 1891 IS_ENTITY_ATTR(tmp->attr_id)); 1892 } else { 1893 ec = ISNS_RSP_INTERNAL_ERROR; 1894 } 1895 1896 if (ec == 0) { 1897 /* set default registration period */ 1898 attr = &entity->attrs[ 1899 ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)]; 1900 if (attr->tag == 0) { 1901 attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID; 1902 attr->len = 4; 1903 attr->value.ui = get_reg_period(); 1904 } 1905 } else if (entity != NULL) { 1906 free(entity); 1907 entity = NULL; 1908 } 1909 } 1910 1911 *p = entity; 1912 *op = tmp; 1913 *op_len = tmp_len; 1914 1915 return (ec); 1916 } 1917 1918 /* 1919 * **************************************************************************** 1920 * 1921 * reg_get_iscsi: 1922 * parse the Operating Attributes of the DevAttrReg message and 1923 * create an iSCSI Storage Node object. 1924 * 1925 * p - the pointer of the object for returning. 1926 * pg_key1 - the pointer of iscsi storage node name for returning. 1927 * op - the operating attributes. 1928 * op_len - the length of the operating attributes. 1929 * return - error code. 1930 * 1931 * **************************************************************************** 1932 */ 1933 static int 1934 reg_get_iscsi( 1935 isns_obj_t **p, 1936 isns_attr_t *pg_key1, 1937 isns_tlv_t **op, 1938 uint16_t *op_len 1939 ) 1940 { 1941 int ec = 0; 1942 1943 isns_tlv_t *tmp; 1944 uint16_t tmp_len; 1945 isns_attr_t *attr; 1946 1947 isns_obj_t *obj = NULL; 1948 1949 tmp = *op; 1950 tmp_len = *op_len; 1951 1952 /* keep the iscsi storage node name for */ 1953 /* parsing a pg object which is immediately */ 1954 /* followed with a PGT by the iscsi storage node */ 1955 pg_key1->tag = PG_KEY1; 1956 pg_key1->len = tmp->attr_len; 1957 pg_key1->value.ptr = (uchar_t *)&tmp->attr_value[0]; 1958 1959 /* parse one iscsi storage node object */ 1960 obj = obj_calloc(OBJ_ISCSI); 1961 if (obj != NULL) { 1962 /* parse key & non-key attributes */ 1963 do { 1964 attr = &obj->attrs[ 1965 ATTR_INDEX_ISCSI(tmp->attr_id)]; 1966 ec = copy_attr(attr, tmp); 1967 NEXT_TLV(tmp, tmp_len); 1968 } while (ec == 0 && 1969 tmp_len >= 8 && 1970 IS_ISCSI_ATTR(tmp->attr_id)); 1971 } else { 1972 /* no memory */ 1973 ec = ISNS_RSP_INTERNAL_ERROR; 1974 } 1975 1976 *p = obj; 1977 *op = tmp; 1978 *op_len = tmp_len; 1979 1980 return (ec); 1981 } 1982 1983 /* 1984 * **************************************************************************** 1985 * 1986 * reg_get_portal: 1987 * parse the Operating Attributes of the DevAttrReg message and 1988 * create a Portal object. 1989 * 1990 * p - the pointer of the object for returning. 1991 * pg_key1 - the pointer of portal ip addr for returning. 1992 * pg_key2 - the pointer of portal port for returning. 1993 * op - the operating attributes. 1994 * op_len - the length of the operating attributes. 1995 * return - error code. 1996 * 1997 * **************************************************************************** 1998 */ 1999 static int 2000 reg_get_portal( 2001 isns_obj_t **p, 2002 isns_attr_t *pg_key1, 2003 isns_attr_t *pg_key2, 2004 isns_tlv_t **op, 2005 uint16_t *op_len 2006 ) 2007 { 2008 int ec = 0; 2009 2010 isns_tlv_t *tmp; 2011 uint16_t tmp_len; 2012 isns_attr_t *attr; 2013 2014 isns_obj_t *obj = NULL; 2015 2016 isns_tlv_t *ip; 2017 2018 tmp = *op; 2019 tmp_len = *op_len; 2020 2021 /* keep the portal ip addr */ 2022 pg_key1->tag = PG_KEY2; 2023 pg_key1->len = tmp->attr_len; 2024 pg_key1->value.ip = (void *)&tmp->attr_value[0]; 2025 ip = tmp; 2026 2027 NEXT_TLV(tmp, tmp_len); 2028 if (tmp_len > 8 && 2029 tmp->attr_id == PORTAL_KEY2 && 2030 tmp->attr_len == 4) { 2031 /* keep the portal port */ 2032 pg_key2->tag = PG_KEY3; 2033 pg_key2->len = tmp->attr_len; 2034 pg_key2->value.ui = ntohl(*(uint32_t *)&tmp->attr_value[0]); 2035 2036 /* parse one portal object */ 2037 obj = obj_calloc(OBJ_PORTAL); 2038 if (obj != NULL) { 2039 /* copy ip addr attribute */ 2040 attr = &obj->attrs[ 2041 ATTR_INDEX_PORTAL(ip->attr_id)]; 2042 ec = copy_attr(attr, ip); 2043 /* copy port attribute */ 2044 if (ec == 0) { 2045 attr = &obj->attrs[ 2046 ATTR_INDEX_PORTAL(tmp->attr_id)]; 2047 ec = copy_attr(attr, tmp); 2048 } 2049 /* parse non-key attributes */ 2050 NEXT_TLV(tmp, tmp_len); 2051 while (ec == 0 && 2052 tmp_len >= 8 && 2053 IS_PORTAL_ATTR(tmp->attr_id)) { 2054 attr = &obj->attrs[ 2055 ATTR_INDEX_PORTAL( 2056 tmp->attr_id)]; 2057 ec = copy_attr(attr, tmp); 2058 NEXT_TLV(tmp, tmp_len); 2059 } 2060 } else { 2061 /* no memory */ 2062 ec = ISNS_RSP_INTERNAL_ERROR; 2063 } 2064 } else { 2065 /* ip address is not followed by port */ 2066 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2067 } 2068 2069 *p = obj; 2070 *op = tmp; 2071 *op_len = tmp_len; 2072 2073 return (ec); 2074 } 2075 2076 /* 2077 * **************************************************************************** 2078 * 2079 * reg_get_pg: 2080 * parse the Operating Attributes of the DevAttrReg message and 2081 * create a Portal Group object. 2082 * 2083 * p - the pointer of the object for returning. 2084 * op - the operating attributes. 2085 * op_len - the length of the operating attributes. 2086 * return - error code. 2087 * 2088 * **************************************************************************** 2089 */ 2090 static int 2091 reg_get_pg( 2092 isns_obj_t **p, 2093 isns_tlv_t **op, 2094 uint16_t *op_len 2095 ) 2096 { 2097 int ec = 0; 2098 2099 isns_tlv_t *tmp; 2100 uint16_t tmp_len; 2101 isns_attr_t *attr; 2102 2103 isns_obj_t *obj = NULL; 2104 2105 tmp = *op; 2106 tmp_len = *op_len; 2107 2108 /* parse a complete pg object */ 2109 obj = obj_calloc(OBJ_PG); 2110 if (obj != NULL) { 2111 /* parse attributes */ 2112 do { 2113 attr = &obj->attrs[ 2114 ATTR_INDEX_PG(tmp->attr_id)]; 2115 ec = copy_attr(attr, tmp); 2116 NEXT_TLV(tmp, tmp_len); 2117 } while (ec == 0 && 2118 tmp_len >= 8 && 2119 IS_PG_ATTR(tmp->attr_id)); 2120 } else { 2121 ec = ISNS_RSP_INTERNAL_ERROR; 2122 } 2123 2124 *p = obj; 2125 *op = tmp; 2126 *op_len = tmp_len; 2127 2128 return (ec); 2129 } 2130 2131 /* 2132 * **************************************************************************** 2133 * 2134 * reg_get_pg1: 2135 * parse the Operating Attributes of the DevAttrReg message and 2136 * create a Portal Group object which is followed to a Portal object. 2137 * 2138 * p - the pointer of the object for returning. 2139 * pgt - the size-3 array of pointers which have the pg portal ip addr, port 2140 * and the pg tag attributes. 2141 * op - the operating attributes. 2142 * op_len - the length of the operating attributes. 2143 * return - error code. 2144 * 2145 * **************************************************************************** 2146 */ 2147 static int 2148 reg_get_pg1( 2149 isns_obj_t **p, 2150 isns_attr_t const *pgt, 2151 isns_tlv_t **op, 2152 uint16_t *op_len 2153 ) 2154 { 2155 int ec = 0; 2156 2157 isns_tlv_t *tmp; 2158 uint16_t tmp_len; 2159 isns_attr_t *attr; 2160 2161 isns_obj_t *obj = NULL; 2162 int i = 0; 2163 2164 tmp = *op; 2165 tmp_len = *op_len; 2166 2167 if (pgt[0].tag == PG_KEY2 && 2168 pgt[1].tag == PG_KEY3) { 2169 /* the pg iscsi storage node name is */ 2170 /* followed to a portal group tag */ 2171 obj = obj_calloc(OBJ_PG); 2172 if (obj != NULL) { 2173 /* copy pg iscsi storage node name */ 2174 attr = &obj->attrs[ 2175 ATTR_INDEX_PG(tmp->attr_id)]; 2176 ec = copy_attr(attr, tmp); 2177 /* copy pg ip addr, pg port & pgt */ 2178 while (ec == 0 && i < 3) { 2179 attr = &obj->attrs[ 2180 ATTR_INDEX_PG(pgt[i].tag)]; 2181 ec = assign_attr(attr, &pgt[i]); 2182 i ++; 2183 } 2184 NEXT_TLV(tmp, tmp_len); 2185 } else { 2186 /* no memory */ 2187 ec = ISNS_RSP_INTERNAL_ERROR; 2188 } 2189 } else { 2190 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2191 } 2192 2193 *p = obj; 2194 *op = tmp; 2195 *op_len = tmp_len; 2196 2197 return (ec); 2198 } 2199 2200 /* 2201 * **************************************************************************** 2202 * 2203 * reg_get_pg2: 2204 * parse the Operating Attributes of the DevAttrReg message and 2205 * create a Portal Group object which is followed to a iSCSI 2206 * Storage Node object. 2207 * 2208 * p - the pointer of the object for returning. 2209 * pgt - the size-3 array of pointers which have the pg iscsi storage 2210 * node name and the pg tag attributes. 2211 * op - the operating attributes. 2212 * op_len - the length of the operating attributes. 2213 * return - error code. 2214 * 2215 * **************************************************************************** 2216 */ 2217 static int 2218 reg_get_pg2( 2219 isns_obj_t **p, 2220 isns_attr_t const *pgt, 2221 isns_tlv_t **op, 2222 uint16_t *op_len 2223 ) 2224 { 2225 int ec = 0; 2226 2227 isns_tlv_t *tmp; 2228 uint16_t tmp_len; 2229 isns_attr_t *attr; 2230 2231 isns_obj_t *obj = NULL; 2232 int i = 0; 2233 2234 isns_tlv_t *ip; 2235 2236 tmp = *op; 2237 tmp_len = *op_len; 2238 2239 /* keep ip address */ 2240 ip = tmp; 2241 NEXT_TLV(tmp, tmp_len); 2242 2243 if (tmp_len > 8 && 2244 /* expect pg portal port */ 2245 tmp->attr_id == PG_KEY3 && 2246 tmp->attr_len == 4 && 2247 /* expect pg tag */ 2248 pgt[2].tag == PG_PGT && 2249 /* expect pg iscsi storage node name only */ 2250 pgt[1].tag == 0 && 2251 pgt[0].tag == PG_KEY1) { 2252 /* the pg portal ip addr & port is followed */ 2253 /* to a pg tag and we have the iscsi storage */ 2254 /* node parsed previously */ 2255 obj = obj_calloc(OBJ_PG); 2256 if (obj != NULL) { 2257 /* copy the pg ip addr */ 2258 attr = &obj->attrs[ 2259 ATTR_INDEX_PG(ip->attr_id)]; 2260 ec = copy_attr(attr, ip); 2261 /* copy the pg port */ 2262 if (ec == 0) { 2263 attr = &obj->attrs[ 2264 ATTR_INDEX_PG(tmp->attr_id)]; 2265 ec = copy_attr(attr, tmp); 2266 } 2267 /* copy pg iscsi storage node name & pgt */ 2268 while (ec == 0 && i < 3) { 2269 attr = &obj->attrs[ 2270 ATTR_INDEX_PG(pgt[i].tag)]; 2271 ec = assign_attr(attr, &pgt[i]); 2272 i += 2; 2273 } 2274 NEXT_TLV(tmp, tmp_len); 2275 } else { 2276 ec = ISNS_RSP_INTERNAL_ERROR; 2277 } 2278 } else { 2279 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2280 } 2281 2282 *p = obj; 2283 *op = tmp; 2284 *op_len = tmp_len; 2285 2286 return (ec); 2287 } 2288 2289 /* 2290 * **************************************************************************** 2291 * 2292 * reg_get_obj: 2293 * parse and create one object from the rest of Operating Attributes 2294 * of the DevAttrReg message, the object can be iSCSI Storage Node, 2295 * Portal or Portal Group. 2296 * 2297 * p - the pointer of the object for returning. 2298 * pgt - an attribute array with size 3, the elements are: 2299 * 0: the first pg key attribute, it is either the name of an 2300 * iscsi storage node object or the ip addr of a portal object. 2301 * 1: the second pg key attribute, i.e. the portal port. 2302 * 2: the portal group tag attribute. 2303 * op - the operating attributes. 2304 * op_len - the length of the operating attributes. 2305 * return - error code. 2306 * 2307 * **************************************************************************** 2308 */ 2309 int 2310 reg_get_obj( 2311 isns_obj_t **p, 2312 isns_attr_t *pgt, 2313 isns_tlv_t **op, 2314 uint16_t *op_len 2315 ) 2316 { 2317 int ec = 0; 2318 2319 int derefd = 0; 2320 2321 uint32_t pg_tag; 2322 2323 if (*op_len == 0) { 2324 *p = NULL; 2325 return (0); 2326 } 2327 2328 switch ((*op)->attr_id) { 2329 case ISCSI_KEY: 2330 ec = reg_get_iscsi(p, &pgt[0], op, op_len); 2331 pgt[1].tag = 0; 2332 pgt[2].tag = 0; 2333 break; 2334 case PORTAL_KEY1: 2335 ec = reg_get_portal(p, &pgt[0], &pgt[1], op, op_len); 2336 pgt[2].tag = 0; 2337 break; 2338 case PG_KEY1: 2339 if (pgt[2].tag == PG_PGT) { 2340 /* pg iscsi storage node name is */ 2341 /* followed to a pgt */ 2342 ec = reg_get_pg1(p, pgt, op, op_len); 2343 } else { 2344 /* a complete pg object */ 2345 ec = reg_get_pg(p, op, op_len); 2346 pgt[0].tag = 0; 2347 pgt[1].tag = 0; 2348 pgt[2].tag = 0; 2349 } 2350 break; 2351 case PG_KEY2: 2352 /* pg portal ip addr is followed to a pgt */ 2353 ec = reg_get_pg2(p, pgt, op, op_len); 2354 break; 2355 case PG_PGT: 2356 switch (pgt[0].tag) { 2357 case 0: 2358 /* portal group tag does not follow */ 2359 /* iscsi storage node or portal object */ 2360 *p = NULL; 2361 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2362 break; 2363 case PG_KEY1: 2364 case PG_KEY2: 2365 pgt[2].tag = PG_PGT; 2366 pgt[2].len = (*op)->attr_len; 2367 pg_tag = 0; 2368 switch ((*op)->attr_len) { 2369 case 4: 2370 pg_tag = ntohl(*(uint32_t *) 2371 &(*op)->attr_value[0]); 2372 case 0: 2373 pgt[2].value.ui = pg_tag; 2374 break; 2375 default: 2376 *p = NULL; 2377 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2378 break; 2379 } 2380 if (ec == 0) { 2381 derefd = 1; 2382 NEXT_TLV(*op, *op_len); 2383 ec = reg_get_obj(p, pgt, op, op_len); 2384 } 2385 break; 2386 default: 2387 /* should never happen */ 2388 ASSERT(0); 2389 *p = NULL; 2390 ec = ISNS_RSP_INTERNAL_ERROR; 2391 break; 2392 } 2393 break; 2394 default: 2395 *p = NULL; 2396 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2397 break; 2398 } 2399 2400 if (ec == 0 && derefd == 0) { 2401 ec = update_deref_obj(*p); 2402 } 2403 2404 if (ec != 0 && *p != NULL) { 2405 free_one_object(*p); 2406 *p = NULL; 2407 } 2408 2409 return (ec); 2410 } 2411 2412 /* 2413 * **************************************************************************** 2414 * 2415 * reg_auth_src: 2416 * Authorize the source attribute the DevAttrReg message. 2417 * The update can only performed by the node who has the owenership. 2418 * 2419 * p - the pointer of the object for returning. 2420 * pgt - an attribute array with size 3, the elements are: 2421 * 0: the first pg key attribute, it is either the name of an 2422 * iscsi storage node object or the ip addr of a portal object. 2423 * 1: the second pg key attribute, i.e. the portal port. 2424 * 2: the portal group tag attribute. 2425 * op - the operating attributes. 2426 * op_len - the length of the operating attributes. 2427 * return - error code. 2428 * 2429 * **************************************************************************** 2430 */ 2431 int 2432 reg_auth_src( 2433 isns_type_t type, 2434 uint32_t uid, 2435 uchar_t *src 2436 ) 2437 { 2438 lookup_ctrl_t lc; 2439 uint32_t puid; 2440 2441 puid = is_parent_there(src); 2442 2443 if (TYPE_OF_PARENT[type] != 0) { 2444 SET_UID_LCP(&lc, type, uid); 2445 uid = cache_lookup(&lc, NULL, cb_get_parent); 2446 type = TYPE_OF_PARENT[type]; 2447 } 2448 2449 if (uid != 0 && puid == 0) { 2450 SET_UID_LCP(&lc, type, uid); 2451 uid = cache_lookup(&lc, NULL, cb_node_child); 2452 } 2453 2454 if (puid != uid) { 2455 return (0); 2456 } 2457 2458 return (1); 2459 } 2460 2461 /* 2462 * **************************************************************************** 2463 * 2464 * is_obj_online: 2465 * determine if the object is currently registered with the server. 2466 * 2467 * obj - the object being checked. 2468 * return - 0: not registered, otherwise registered. 2469 * 2470 * **************************************************************************** 2471 */ 2472 int 2473 is_obj_online( 2474 const isns_obj_t *obj 2475 ) 2476 { 2477 int online = 1; 2478 2479 switch (obj->type) { 2480 case OBJ_ISCSI: 2481 online = obj->attrs[ATTR_INDEX_ISCSI( 2482 ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui == 0 ? 0 : 1; 2483 break; 2484 default: 2485 break; 2486 } 2487 2488 return (online); 2489 } 2490 2491 static int 2492 set_obj_offline( 2493 isns_obj_t *obj 2494 ) 2495 { 2496 switch (obj->type) { 2497 case OBJ_ISCSI: 2498 obj->attrs[ATTR_INDEX_ISCSI( 2499 ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui = 0; 2500 break; 2501 default: 2502 break; 2503 } 2504 2505 return (0); 2506 } 2507 2508 /* 2509 * **************************************************************************** 2510 * 2511 * assoc_clone: 2512 * clone the association object. 2513 * 2514 * p - the object being cloned. 2515 * clone_flag - 0: the object is being removed; 2516 * 1: only the association is being removed. 2517 * return - the clone object. 2518 * 2519 * **************************************************************************** 2520 */ 2521 void * 2522 assoc_clone( 2523 void *p, 2524 int clone_flag 2525 ) 2526 { 2527 isns_type_t type; 2528 isns_obj_t *clone; 2529 const isns_attr_t *src_attr; 2530 isns_attr_t *dst_attr; 2531 uint32_t id, op; 2532 int i = 0; 2533 2534 const isns_obj_t *obj; 2535 uint32_t dd_flag; 2536 int online; 2537 2538 int state; 2539 2540 obj = (isns_obj_t *)p; 2541 2542 if (obj->type != OBJ_ISCSI) { 2543 return (NULL); 2544 } 2545 2546 dd_flag = (get_dd_id(get_obj_uid(obj), ISNS_DEFAULT_DD_ID) == 0) ? 2547 0 : 1; 2548 online = is_obj_online(obj); 2549 2550 state = (clone_flag << 2) | (dd_flag << 1) | online; 2551 2552 /* clone_flag dd_flag online action */ 2553 /* 0 0 0 ASSERT(0) */ 2554 /* 0 0 1 NULL */ 2555 /* 0 1 0 itself */ 2556 /* 0 1 1 clone it */ 2557 /* 1 0 0 NULL */ 2558 /* 1 0 1 itself */ 2559 /* 1 1 0 itself */ 2560 /* 1 1 1 itself */ 2561 2562 switch (state) { 2563 case 0: 2564 ASSERT(0); 2565 case 1: 2566 case 4: 2567 return (NULL); 2568 case 2: 2569 case 5: 2570 case 6: 2571 case 7: 2572 return (p); 2573 case 3: 2574 default: 2575 break; 2576 } 2577 2578 type = obj->type; 2579 clone = obj_calloc(type); 2580 2581 if (clone != NULL) { 2582 id = UID_ATTR_INDEX[type]; 2583 src_attr = &(obj->attrs[id]); 2584 dst_attr = &(clone->attrs[id]); 2585 if (assign_attr(dst_attr, src_attr) != 0) { 2586 free_one_object(clone); 2587 return (NULL); 2588 } 2589 2590 while (i < MAX_KEY_ATTRS) { 2591 op = KEY_ATTR_OP[type][i]; 2592 if (op != 0) { 2593 id = KEY_ATTR_INDEX[type][i]; 2594 src_attr = &(obj->attrs[id]); 2595 dst_attr = &(clone->attrs[id]); 2596 if (assign_attr(dst_attr, src_attr) != 0) { 2597 free_one_object(clone); 2598 return (NULL); 2599 } 2600 } else { 2601 break; 2602 } 2603 i ++; 2604 } 2605 } 2606 2607 return ((void *)clone); 2608 } 2609 2610 /* 2611 * **************************************************************************** 2612 * 2613 * free_one_object: 2614 * free up one object. 2615 * 2616 * obj - the object being freed. 2617 * 2618 * **************************************************************************** 2619 */ 2620 void 2621 free_one_object( 2622 isns_obj_t *obj 2623 ) 2624 { 2625 int i; 2626 uint32_t *cuid; 2627 if (obj == NULL) { 2628 return; 2629 } 2630 for (i = 0; i < NUM_OF_ATTRS[obj->type]; i++) { 2631 isns_attr_t *attr = &obj->attrs[i]; 2632 switch (attr->tag) { 2633 case ISNS_EID_ATTR_ID: 2634 case ISNS_ISCSI_NAME_ATTR_ID: 2635 case ISNS_ISCSI_ALIAS_ATTR_ID: 2636 case ISNS_ISCSI_AUTH_METHOD_ATTR_ID: 2637 case ISNS_PG_ISCSI_NAME_ATTR_ID: 2638 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 2639 case ISNS_PORTAL_NAME_ATTR_ID: 2640 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 2641 case ISNS_DD_SET_NAME_ATTR_ID: 2642 case ISNS_DD_NAME_ATTR_ID: 2643 case ISNS_DD_ISCSI_NAME_ATTR_ID: 2644 case ISNS_DD_FC_PORT_NAME_ATTR_ID: 2645 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID: 2646 #ifdef DEBUG 2647 if (verbose_mc) { 2648 printf("memory(%d) deallocated\n", 2649 attr->len); 2650 } 2651 #endif 2652 free(attr->value.ptr); 2653 attr->value.ptr = NULL; 2654 break; 2655 default: 2656 break; 2657 } 2658 } 2659 2660 /* free child uids */ 2661 i = 0; 2662 while (i < NUM_OF_CHILD[obj->type]) { 2663 cuid = get_child_n(obj, i); 2664 free(cuid); 2665 i ++; 2666 } 2667 2668 /* at last, free the object itself */ 2669 #ifdef DEBUG 2670 if (verbose_mc) { 2671 printf("object(%d) deallocated\n", obj->type); 2672 } 2673 #endif 2674 free(obj); 2675 } 2676 2677 /* 2678 * **************************************************************************** 2679 * 2680 * free_object: 2681 * free up one object. 2682 * 2683 * obj - the object being freed. 2684 * 2685 * **************************************************************************** 2686 */ 2687 void 2688 free_object( 2689 isns_obj_t *obj 2690 ) 2691 { 2692 free_one_object(obj); 2693 } 2694 2695 /* 2696 * **************************************************************************** 2697 * 2698 * set_parent_obj: 2699 * set the parent object UID. 2700 * 2701 * obj - the child object. 2702 * puid- the parent object UID. 2703 * return - error code. 2704 * 2705 * **************************************************************************** 2706 */ 2707 int 2708 set_parent_obj( 2709 isns_obj_t *obj, 2710 uint32_t puid 2711 ) 2712 { 2713 uint32_t *const p = get_parent_p(obj); 2714 if (p != NULL) { 2715 *p = puid; 2716 } 2717 2718 return (0); 2719 } 2720 2721 /* 2722 * **************************************************************************** 2723 * 2724 * buff_child_obj: 2725 * add a child object UID to the child object array. 2726 * 2727 * obj - the parent object. 2728 * child_type - the type of the child object. 2729 * number - the number of the child object. 2730 * return - the length of the child object UID array. 2731 * 2732 * **************************************************************************** 2733 */ 2734 int 2735 buff_child_obj( 2736 const isns_type_t ptype, 2737 const isns_type_t ctype, 2738 const void *c, 2739 void const ***child 2740 ) 2741 { 2742 int ec = 0; 2743 2744 int i = 0; 2745 void const ***pp, **p; 2746 uint32_t num, new_num; 2747 2748 pp = NULL; 2749 /* get the pointer of the array which the child belongs to */ 2750 while (i < NUM_OF_CHILD[ptype]) { 2751 if (TYPE_OF_CHILD[ptype][i] == ctype) { 2752 pp = &child[i]; 2753 break; 2754 } 2755 i ++; 2756 } 2757 2758 /* the child type is not applicable */ 2759 if (pp == NULL) { 2760 return (ec); 2761 } 2762 2763 p = *pp; 2764 /* get an empty slot from the uid array for this child */ 2765 if (p != NULL) { 2766 num = (uint32_t)*p; 2767 i = 0; 2768 while (i < num) { 2769 if (p[++i] == NULL) { 2770 /* found it */ 2771 p[i] = c; 2772 return (ec); 2773 } 2774 } 2775 p = *pp; 2776 new_num = num + 1; 2777 } else { 2778 num = 0; 2779 new_num = 1; 2780 } 2781 2782 /* the array is full, enlarge the child uid array */ 2783 p = (void const **)realloc(p, (new_num + 1) * sizeof (void *)); 2784 if (p != NULL) { 2785 *pp = p; 2786 *p = (void *)new_num; 2787 p[new_num] = c; 2788 } else { 2789 ec = ISNS_RSP_INTERNAL_ERROR; 2790 } 2791 2792 return (ec); 2793 } 2794 2795 /* 2796 * **************************************************************************** 2797 * 2798 * update_child_object: 2799 * update the child object of a network entity object. 2800 * 2801 * puid - the UID of the parent object, i.e. the network entity object. 2802 * child_type - the type of the child object. 2803 * child_uid - the uid of the child object. 2804 * return - error code. 2805 * 2806 * **************************************************************************** 2807 */ 2808 int 2809 update_child_obj( 2810 const isns_type_t ptype, 2811 const uint32_t puid, 2812 void const ***child, 2813 int child_flag 2814 ) 2815 { 2816 int ec = 0; 2817 2818 lookup_ctrl_t lc; 2819 2820 SET_UID_LCP(&lc, ptype, puid); 2821 2822 lc.data[1].ptr = (uchar_t *)child; 2823 lc.data[2].ui = child_flag; 2824 2825 ec = cache_lookup(&lc, NULL, cb_add_child); 2826 2827 return (ec); 2828 } 2829 2830 int 2831 update_ref_obj( 2832 const isns_obj_t *obj 2833 ) 2834 { 2835 uint32_t uid; 2836 lookup_ctrl_t lc; 2837 isns_type_t t; 2838 2839 t = obj->type; 2840 2841 if (TYPE_OF_REF[t][0] != 0) { 2842 (void) setup_ref_lcp(&lc, obj, NULL); 2843 2844 lc.id[2] = t; 2845 lc.data[2].ui = get_obj_uid(obj); 2846 2847 uid = 0; 2848 do { 2849 lc.curr_uid = uid; 2850 (void) cache_lookup(&lc, &uid, cb_set_ref); 2851 } while (uid != 0); 2852 } 2853 2854 return (0); 2855 } 2856 2857 /* 2858 * **************************************************************************** 2859 * 2860 * verify_ref_obj: 2861 * update the reference bit of a portal group object. 2862 * 2863 * obj - the object being ref'ed. 2864 * return - error code. 2865 * 2866 * **************************************************************************** 2867 */ 2868 int 2869 verify_ref_obj( 2870 const isns_type_t ptype, 2871 const uint32_t puid, 2872 void const ***child 2873 ) 2874 { 2875 int ec = 0; 2876 2877 lookup_ctrl_t lc; 2878 2879 SET_UID_LCP(&lc, ptype, puid); 2880 2881 lc.data[1].ptr = (uchar_t *)child; 2882 2883 ec = cache_lookup(&lc, NULL, cb_verify_ref); 2884 2885 return (ec); 2886 } 2887 2888 int 2889 update_deref_obj( 2890 isns_obj_t *obj 2891 ) 2892 { 2893 int ec = 0; 2894 2895 isns_type_t t, rt; 2896 lookup_ctrl_t lc; 2897 int i, ref_count; 2898 2899 uint32_t uid, *refp; 2900 2901 t = obj->type; 2902 i = ref_count = 0; 2903 while (i < NUM_OF_REF[t]) { 2904 rt = TYPE_OF_REF[t][i + 1]; 2905 (void) setup_deref_lcp(&lc, obj, rt); 2906 uid = is_obj_there(&lc); 2907 if (uid != 0) { 2908 refp = get_ref_p(obj, lc.type); 2909 *refp = uid; 2910 ref_count ++; 2911 } 2912 i ++; 2913 } 2914 2915 if (i > 0 && ref_count == 0) { 2916 ec = ISNS_RSP_INVALID_REGIS; 2917 } 2918 2919 return (ec); 2920 } 2921 2922 /* 2923 * **************************************************************************** 2924 * 2925 * register_object: 2926 * add one object to the object container. 2927 * 2928 * obj - the object being added. 2929 * uid_p- the pointer for returning object UID. 2930 * update_p- the pointer for returning flag which indicates if the object 2931 * is newly registered or updated with an existing one. 2932 * return - error code. 2933 * 2934 * **************************************************************************** 2935 */ 2936 int 2937 register_object( 2938 isns_obj_t *obj, 2939 uint32_t *uid_p, 2940 int *update_p 2941 ) 2942 { 2943 return (cache_add(obj, 0, uid_p, update_p)); 2944 } 2945 2946 /* 2947 * **************************************************************************** 2948 * 2949 * register_assoc: 2950 * add one association object to the object container, the association 2951 * object has only the information for discovery domain membership, i.e. 2952 * a name and UID only. 2953 * 2954 * obj - the association object being added. 2955 * uid_p- the pointer for returning object UID. 2956 * return - error code. 2957 * 2958 * **************************************************************************** 2959 */ 2960 int 2961 register_assoc( 2962 isns_obj_t *obj, 2963 uint32_t *uid_p 2964 ) 2965 { 2966 return (cache_add(obj, 1, uid_p, NULL)); 2967 } 2968 2969 /* 2970 * **************************************************************************** 2971 * 2972 * is_obj_there: 2973 * check if the object is registered or not. 2974 * 2975 * lcp - the lookup control data. 2976 * return - the object UID. 2977 * 2978 * **************************************************************************** 2979 */ 2980 uint32_t 2981 is_obj_there( 2982 lookup_ctrl_t *lcp 2983 ) 2984 { 2985 uint32_t uid; 2986 2987 (void) cache_lookup(lcp, &uid, NULL); 2988 2989 return (uid); 2990 } 2991 2992 uint32_t 2993 is_parent_there( 2994 uchar_t *src 2995 ) 2996 { 2997 lookup_ctrl_t lc; 2998 2999 lc.curr_uid = 0; 3000 lc.type = OBJ_ISCSI; 3001 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 3002 lc.op[0] = OP_STRING; 3003 lc.data[0].ptr = src; 3004 lc.op[1] = 0; 3005 3006 return (cache_lookup(&lc, NULL, cb_get_parent)); 3007 } 3008 3009 /* 3010 * **************************************************************************** 3011 * 3012 * setup_ref_lcp: 3013 * prepare the lookup control data for looking up a portal group 3014 * object which references to a iscsi stroage node and/or a portal 3015 * object. 3016 * 3017 * lcp - the lookup control data. 3018 * iscsi- the ref'ed iscsi storage node object. 3019 * portal- the ref'ed portal object. 3020 * return - error code. 3021 * 3022 * **************************************************************************** 3023 */ 3024 static int 3025 setup_ref_lcp( 3026 lookup_ctrl_t *lcp, 3027 const isns_obj_t *iscsi, 3028 const isns_obj_t *portal 3029 ) 3030 { 3031 int i = 0, j = 0; 3032 3033 lcp->curr_uid = 0; 3034 lcp->type = TYPE_OF_REF[iscsi->type][0]; 3035 3036 /* extrace the matching attributes from iscsi storage node object */ 3037 while (iscsi != NULL && 3038 i < MAX_REF_MATCH && 3039 REF_MATCH_OPS[iscsi->type][i] > 0) { 3040 lcp->id[i] = REF_MATCH_ID2[iscsi->type][i]; 3041 lcp->op[i] = REF_MATCH_OPS[iscsi->type][i]; 3042 lcp->data[i].ptr = iscsi->attrs[ 3043 REF_MATCH_ID1[iscsi->type][i]].value.ptr; 3044 i ++; 3045 } 3046 3047 /* extrace the matching attributes from portal object */ 3048 while (portal != NULL && 3049 i < MAX_LOOKUP_CTRL && 3050 j < MAX_REF_MATCH && 3051 REF_MATCH_OPS[portal->type][j] > 0) { 3052 lcp->id[i] = REF_MATCH_ID2[portal->type][j]; 3053 lcp->op[i] = REF_MATCH_OPS[portal->type][j]; 3054 lcp->data[i].ptr = portal->attrs[ 3055 REF_MATCH_ID1[portal->type][j]].value.ptr; 3056 j ++; 3057 i ++; 3058 } 3059 3060 if (i < MAX_LOOKUP_CTRL) { 3061 lcp->op[i] = 0; 3062 } 3063 3064 return (0); 3065 } 3066 3067 static int 3068 setup_deref_lcp( 3069 lookup_ctrl_t *lcp, 3070 const isns_obj_t *pg, 3071 isns_type_t t 3072 ) 3073 { 3074 int i = 0; 3075 3076 lcp->curr_uid = 0; 3077 lcp->type = t; 3078 3079 /* extrace the matching attributes from iscsi storage node object */ 3080 while (i < MAX_REF_MATCH && 3081 REF_MATCH_OPS[t][i] > 0) { 3082 lcp->id[i] = REF_MATCH_ID1[t][i]; 3083 lcp->op[i] = REF_MATCH_OPS[t][i]; 3084 lcp->data[i].ptr = pg->attrs[ 3085 REF_MATCH_ID2[t][i]].value.ptr; 3086 i ++; 3087 } 3088 3089 if (i < MAX_LOOKUP_CTRL) { 3090 lcp->op[i] = 0; 3091 } 3092 3093 return (0); 3094 } 3095 3096 /* 3097 * **************************************************************************** 3098 * 3099 * setup_parent_lcp: 3100 * prepare the lookup control data for looking up parent object 3101 * with a child object. 3102 * 3103 * lcp - the lookup control data. 3104 * obj - the child object. 3105 * return - parent object UID. 3106 * 3107 * **************************************************************************** 3108 */ 3109 static uint32_t 3110 setup_parent_lcp( 3111 lookup_ctrl_t *lcp, 3112 isns_obj_t *obj 3113 ) 3114 { 3115 isns_type_t ptype; 3116 uint32_t puid; 3117 3118 puid = get_parent_uid(obj); 3119 if (puid != 0) { 3120 ptype = TYPE_OF_PARENT[obj->type]; 3121 SET_UID_LCP(lcp, ptype, puid); 3122 lcp->data[1].ui = obj->type; 3123 lcp->data[2].ui = get_obj_uid(obj); 3124 } 3125 3126 return (puid); 3127 } 3128 3129 static int 3130 cb_get_parent( 3131 void *p1, 3132 /* LINTED E_FUNC_ARG_UNUSED */ 3133 void *p2 3134 ) 3135 { 3136 return (get_parent_uid(p1)); 3137 } 3138 3139 static int 3140 cb_node_child( 3141 void *p1, 3142 /* LINTED E_FUNC_ARG_UNUSED */ 3143 void *p2 3144 ) 3145 { 3146 isns_obj_t *obj = (isns_obj_t *)p1; 3147 3148 uint32_t num, uid; 3149 3150 uint32_t *cuid = get_child_t(obj, OBJ_ISCSI); 3151 3152 if (cuid != NULL) { 3153 num = *cuid; 3154 } else { 3155 num = 0; 3156 } 3157 3158 while (num > 0) { 3159 uid = *++cuid; 3160 if (uid != 0) { 3161 return (uid); 3162 } 3163 num --; 3164 } 3165 3166 return (0); 3167 } 3168 3169 /* 3170 * **************************************************************************** 3171 * 3172 * cb_set_ref: 3173 * callback function which sets the reference bit to 1 according to 3174 * the type of object. 3175 * 3176 * p1 - the object. 3177 * p2 - the lcp. 3178 * return - error code. 3179 * 3180 * **************************************************************************** 3181 */ 3182 static int 3183 cb_set_ref( 3184 void *p1, 3185 void *p2 3186 ) 3187 { 3188 isns_obj_t *obj = (isns_obj_t *)p1; 3189 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3190 3191 isns_type_t t; 3192 uint32_t u; 3193 3194 uint32_t *refp; 3195 3196 t = lcp->id[2]; 3197 u = lcp->data[2].ui; 3198 refp = get_ref_p(obj, t); 3199 *refp = u; 3200 3201 /* successful */ 3202 return (0); 3203 } 3204 3205 /* 3206 * **************************************************************************** 3207 * 3208 * cb_clear_ref: 3209 * callback function which clears the reference bit according to 3210 * the type of object. 3211 * 3212 * p1 - the object. 3213 * p2 - the lcp. 3214 * return - 1: the object is no longer ref'ed, 0: otherwise. 3215 * 3216 * **************************************************************************** 3217 */ 3218 static int 3219 cb_clear_ref( 3220 void *p1, 3221 void *p2 3222 ) 3223 { 3224 isns_obj_t *obj = (isns_obj_t *)p1; 3225 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3226 3227 isns_type_t t; 3228 uint32_t *refp; 3229 3230 int i = 0; 3231 uint32_t ref; 3232 3233 t = lcp->data[2].ui; 3234 refp = get_ref_p(obj, t); 3235 *refp = 0; 3236 3237 while (i < NUM_OF_REF[obj->type]) { 3238 ref = get_ref_n(obj, i); 3239 if (ref != 0) { 3240 return (0); 3241 } 3242 i ++; 3243 } 3244 3245 return (1); 3246 } 3247 3248 static int 3249 cb_add_child( 3250 void *p1, 3251 void *p2 3252 ) 3253 { 3254 isns_obj_t *obj = (isns_obj_t *)p1; 3255 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3256 3257 const void ***child; 3258 const void **vpp; 3259 uint32_t vnum; 3260 int child_flag; 3261 3262 uint32_t **upp, *up; 3263 uint32_t num; 3264 3265 isns_obj_t *o; 3266 3267 int i = 0; 3268 3269 child = (const void ***)lcp->data[1].ptr; 3270 child_flag = lcp->data[2].ui; 3271 3272 while (i < NUM_OF_CHILD[obj->type]) { 3273 vpp = child[i]; 3274 if (vpp != NULL && 3275 (vnum = (uint32_t)*vpp) > 0 && 3276 *(vpp + 1) != NULL) { 3277 upp = get_child_np(obj, i); 3278 if (*upp == NULL) { 3279 if (child_flag == 0 && 3280 sizeof (typeof (**upp)) == 3281 sizeof (typeof (**child))) { 3282 *upp = (uint32_t *)vpp; 3283 vpp = NULL; 3284 child[i] = NULL; 3285 } 3286 num = vnum; 3287 } else { 3288 num = **upp + vnum; 3289 } 3290 if (vpp != NULL) { 3291 /* copy required */ 3292 up = (uint32_t *)realloc(*upp, 3293 (num + 1) * sizeof (uint32_t)); 3294 if (up == NULL) { 3295 return (ISNS_RSP_INTERNAL_ERROR); 3296 } 3297 *upp = up; 3298 *up = num; 3299 up += num; 3300 vpp += vnum; 3301 while (vnum > 0) { 3302 if (*vpp == NULL) { 3303 *up = 0; 3304 } else if (child_flag == 0) { 3305 *up = (uint32_t)*vpp; 3306 *vpp = NULL; 3307 } else { 3308 o = (isns_obj_t *)*vpp; 3309 *up = get_obj_uid(o); 3310 if (is_obj_online(o) == 0) { 3311 free_object(o); 3312 } 3313 *vpp = NULL; 3314 } 3315 up --; 3316 vpp --; 3317 vnum --; 3318 } 3319 } 3320 } 3321 i ++; 3322 } 3323 3324 return (0); 3325 } 3326 3327 /* 3328 * **************************************************************************** 3329 * 3330 * cb_remove_child: 3331 * callback function which removes a child object UID from the 3332 * children objet UID array of the parent object. 3333 * 3334 * p1 - the object. 3335 * p2 - the lcp. 3336 * return - 1: no more such type of child object, 0: otherwise. 3337 * 3338 * **************************************************************************** 3339 */ 3340 static int 3341 cb_remove_child( 3342 void *p1, 3343 void *p2 3344 ) 3345 { 3346 isns_obj_t *obj = (isns_obj_t *)p1; 3347 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3348 uint32_t child_type = lcp->data[1].ui; 3349 uint32_t child_uid = lcp->data[2].ui; 3350 uint32_t *cuidp, cuid, num_of_child = 0; 3351 int i; 3352 3353 /* get the children object UID array */ 3354 cuidp = get_child_t(obj, child_type); 3355 if (cuidp != NULL) { 3356 num_of_child = *cuidp; 3357 } 3358 3359 /* remove it */ 3360 while (num_of_child > 0) { 3361 cuid = *++cuidp; 3362 if (cuid == child_uid) { 3363 *cuidp = 0; 3364 break; 3365 } 3366 num_of_child --; 3367 } 3368 3369 /* check if all of child object UIDs are removed */ 3370 i = 0; 3371 while (i < NUM_OF_CHILD[obj->type]) { 3372 cuidp = get_child_n(obj, i); 3373 if (cuidp != NULL) { 3374 num_of_child = *cuidp; 3375 while (num_of_child > 0) { 3376 cuid = *++cuidp; 3377 if (cuid != 0) { 3378 return (0); 3379 } 3380 num_of_child --; 3381 } 3382 } 3383 i ++; 3384 } 3385 3386 return (1); 3387 } 3388 3389 static int 3390 cb_verify_ref( 3391 void *p1, 3392 void *p2 3393 ) 3394 { 3395 int ec = 0; 3396 3397 isns_obj_t *parent = (isns_obj_t *)p1; 3398 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3399 3400 const void ***child; 3401 3402 const void **vpp; 3403 const void *vp; 3404 uint32_t vnum; 3405 3406 const void **evpp; 3407 const void *evp; 3408 uint32_t evnum; 3409 3410 isns_type_t pt; /* parent object type */ 3411 isns_type_t ct; /* child object type */ 3412 isns_type_t rt; /* ref object type */ 3413 isns_type_t et; /* peer object type */ 3414 3415 uint32_t *up; 3416 uint32_t u; 3417 uint32_t unum; 3418 3419 lookup_ctrl_t lc; 3420 uint8_t flag[MAX_OBJ_TYPE + 1] = { 0 }; 3421 3422 int i, j, k; 3423 3424 pt = parent->type; 3425 3426 child = (const void ***)lcp->data[1].ptr; 3427 3428 for (i = 0; i < NUM_OF_CHILD[pt]; i++) { 3429 ct = TYPE_OF_CHILD[pt][i]; 3430 rt = TYPE_OF_REF[ct][0]; 3431 if (rt == 0) { 3432 continue; 3433 } 3434 3435 et = TYPE_OF_REF[ct][1]; 3436 vpp = child[i]; 3437 if (vpp != NULL) { 3438 vnum = (uint32_t)*vpp; 3439 up = get_child_t(parent, et); 3440 if (up != NULL) { 3441 unum = *up; 3442 } else { 3443 unum = 0; 3444 } 3445 } else { 3446 vnum = 0; 3447 } 3448 3449 j = vnum; 3450 while (j > 0) { 3451 vp = vpp[j]; 3452 if (vp != NULL) { 3453 (void) setup_ref_lcp(&lc, vp, NULL); 3454 k = unum; 3455 while (k > 0) { 3456 u = up[k]; 3457 if (u != 0) { 3458 ec = ref_new2old( 3459 &lc, et, u, vp); 3460 if (ec != 0) { 3461 return (ec); 3462 } 3463 } 3464 k --; 3465 } /* End of while each unum */ 3466 } 3467 j --; 3468 } /* End of while each vnum */ 3469 3470 if (flag[ct] != 0) { 3471 continue; 3472 } 3473 3474 evnum = 0; 3475 j = 0; 3476 while (j < NUM_OF_CHILD[pt]) { 3477 if (TYPE_OF_CHILD[pt][j] == et) { 3478 evpp = child[j]; 3479 if (evpp != NULL) { 3480 evnum = (uint32_t)*evpp; 3481 } 3482 break; 3483 } 3484 j ++; 3485 } 3486 3487 j = vnum; 3488 while (j > 0) { 3489 vp = vpp[j]; 3490 k = evnum; 3491 while (k > 0) { 3492 evp = evpp[k]; 3493 if (vp != NULL && evp != NULL) { 3494 (void) setup_ref_lcp(&lc, vp, evp); 3495 ec = ref_new2new(&lc, vp, evp); 3496 if (ec != 0) { 3497 return (ec); 3498 } 3499 } 3500 k --; 3501 } 3502 j --; 3503 } /* End of while each vnum */ 3504 3505 flag[et] = 1; 3506 } /* End of for each type of child */ 3507 3508 return (ec); 3509 } 3510 3511 static int 3512 cb_ref_new2old( 3513 void *p1, 3514 void *p2 3515 ) 3516 { 3517 isns_obj_t *obj = (isns_obj_t *)p1; 3518 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3519 3520 isns_type_t et; 3521 uint32_t uu; 3522 3523 uint32_t ref; 3524 3525 int match; 3526 3527 et = lcp->id[2]; 3528 uu = lcp->data[2].ui; 3529 3530 ref = get_ref_t(obj, et); 3531 3532 if (ref == uu) { 3533 match = 1; 3534 } else { 3535 match = 0; 3536 } 3537 3538 return (match); 3539 } 3540 3541 static int 3542 cb_new_ref( 3543 void *p1, 3544 void *p2 3545 ) 3546 { 3547 int ec = 0; 3548 3549 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3550 isns_obj_t *a = (isns_obj_t *)p1; 3551 isns_obj_t *b = (isns_obj_t *)lcp->data[2].ptr; 3552 3553 ec = new_ref(a, b); 3554 3555 return (ec); 3556 } 3557 3558 static int 3559 ref_new2old( 3560 lookup_ctrl_t *lcp, 3561 isns_type_t et, 3562 uint32_t uu, 3563 const isns_obj_t *vp 3564 ) 3565 { 3566 int ec = 0; 3567 3568 int match; 3569 uint32_t uid; 3570 3571 lookup_ctrl_t lc; 3572 3573 lcp->id[2] = et; 3574 lcp->data[2].ui = uu; 3575 3576 uid = 0; 3577 do { 3578 lcp->curr_uid = uid; 3579 match = cache_lookup(lcp, &uid, cb_ref_new2old); 3580 } while (match == 0 && uid != 0); 3581 3582 if (match == 0) { 3583 /* no such ref, create a default one */ 3584 SET_UID_LCP(&lc, et, uu); 3585 3586 lc.data[2].ptr = (uchar_t *)vp; 3587 3588 ec = cache_lookup(&lc, NULL, cb_new_ref); 3589 } 3590 3591 return (ec); 3592 } 3593 3594 static int 3595 ref_new2new( 3596 lookup_ctrl_t *lcp, 3597 const isns_obj_t *p1, 3598 const isns_obj_t *p2 3599 ) 3600 { 3601 int ec = 0; 3602 3603 if (is_obj_there(lcp) != 0) { 3604 return (0); 3605 } 3606 3607 ec = new_ref(p1, p2); 3608 3609 return (ec); 3610 } 3611 3612 static int 3613 new_ref( 3614 const isns_obj_t *p1, 3615 const isns_obj_t *p2 3616 ) 3617 { 3618 int ec = 0; 3619 3620 isns_obj_t *obj; 3621 3622 obj = make_ref[p1->type](p1, p2); 3623 if (obj != NULL) { 3624 ec = register_object(obj, NULL, NULL); 3625 } else { 3626 ec = ISNS_RSP_INTERNAL_ERROR; 3627 } 3628 3629 return (ec); 3630 } 3631 3632 /* 3633 * **************************************************************************** 3634 * 3635 * do_dereg: 3636 * Physically remove an object along with the children objects, 3637 * the reference object and the parent object recursively. 3638 * Apporiate SCN is triggered. 3639 * 3640 * lcp - the lookup control for the object being removed. 3641 * parent_flag - 1: the object being removed is the parent object; 3642 * 0: otherwise. 3643 * child_flag - 1: the object being removed is a child object; 3644 * 0: otherwise. 3645 * pending - 1: do not remove the ESI entry immediately; 3646 * 0: remove the ESI entry without any delay. 3647 * return - error code. 3648 * 3649 * **************************************************************************** 3650 */ 3651 static int 3652 do_dereg( 3653 lookup_ctrl_t *lcp, 3654 int parent_flag, 3655 int child_flag, 3656 int pending 3657 ) 3658 { 3659 int ec = 0; 3660 3661 isns_obj_t *obj; 3662 uint32_t *cuidp, num; 3663 isns_type_t type; 3664 uint32_t uid; 3665 int i; 3666 3667 /* remove the object from object container */ 3668 obj = cache_remove(lcp, 0); 3669 3670 if (obj == NULL) { 3671 return (0); 3672 } 3673 3674 /* trigger a scn */ 3675 if (scn_q != NULL) { 3676 (void) make_scn(ISNS_OBJECT_REMOVED, obj); 3677 } 3678 3679 /* dereg children */ 3680 i = 0; 3681 while (ec == 0 && !parent_flag && 3682 i < NUM_OF_CHILD[obj->type]) { 3683 type = TYPE_OF_CHILD[obj->type][i]; 3684 cuidp = get_child_n(obj, i); 3685 if (cuidp != NULL) { 3686 num = *cuidp; 3687 } else { 3688 num = 0; 3689 } 3690 while (ec == 0 && num > 0) { 3691 uid = cuidp[num]; 3692 if (uid != 0) { 3693 SET_UID_LCP(lcp, type, uid); 3694 ec = do_dereg(lcp, 3695 parent_flag, 3696 1, 3697 pending); 3698 } 3699 num --; 3700 } 3701 i ++; 3702 } 3703 3704 /* clear the ref bit on the ref'd object */ 3705 if (ec == 0 && TYPE_OF_REF[obj->type][0] > 0) { 3706 uid = 0; 3707 do { 3708 (void) setup_ref_lcp(lcp, obj, NULL); 3709 lcp->curr_uid = uid; 3710 lcp->data[2].ui = obj->type; 3711 if (cache_lookup(lcp, &uid, cb_clear_ref) != 0) { 3712 UPDATE_LCP_UID(lcp, uid); 3713 ec = do_dereg(lcp, 3714 parent_flag, 3715 child_flag, 3716 pending); 3717 } 3718 } while (uid != 0); 3719 } 3720 3721 /* remove it from the parent */ 3722 if (ec == 0 && !child_flag && 3723 TYPE_OF_PARENT[obj->type] > 0 && 3724 (uid = setup_parent_lcp(lcp, obj)) != 0) { 3725 if (cache_lookup(lcp, NULL, cb_remove_child) != 0) { 3726 UPDATE_LCP_UID(lcp, uid); 3727 ec = do_dereg(lcp, 3728 1, 3729 child_flag, 3730 0); 3731 } 3732 } 3733 3734 if (ec == 0 && !child_flag) { 3735 /* remove it from persistent data store */ 3736 if (sys_q) { 3737 ec = write_data(DATA_DELETE, obj); 3738 } 3739 /* remove esi event entry */ 3740 if (ec == 0) { 3741 (void) esi_remove_obj(obj, pending); 3742 } 3743 3744 /* save the parent uid for caller */ 3745 if (TYPE_OF_PARENT[obj->type] != 0) { 3746 lcp->curr_uid = get_parent_uid(obj); 3747 } else { 3748 /* it's the parent itself */ 3749 lcp->curr_uid = get_obj_uid(obj); 3750 } 3751 } 3752 3753 /* remove this portal from scn registry */ 3754 if (ec == 0 && 3755 obj->type == OBJ_PORTAL) { 3756 (void) remove_scn_portal(get_obj_uid(obj)); 3757 } 3758 3759 /* free the object */ 3760 (void) free_object(obj); 3761 3762 return (ec); 3763 } 3764 3765 /* 3766 * **************************************************************************** 3767 * 3768 * dereg_assoc: 3769 * Remove one association object from object container. 3770 * 3771 * lcp - the lookup control for the object being removed. 3772 * return - error code. 3773 * 3774 * **************************************************************************** 3775 */ 3776 int 3777 dereg_assoc( 3778 lookup_ctrl_t *lcp 3779 ) 3780 { 3781 isns_obj_t *obj; 3782 3783 obj = cache_remove(lcp, 1); 3784 3785 /* free the object */ 3786 if (obj != NULL) { 3787 free_object(obj); 3788 } 3789 3790 return (0); 3791 } 3792 3793 /* 3794 * **************************************************************************** 3795 * 3796 * dereg_object: 3797 * Remove one object from object container. 3798 * 3799 * lcp - the lookup control for the object being removed. 3800 * return - error code. 3801 * 3802 * **************************************************************************** 3803 */ 3804 int 3805 dereg_object( 3806 lookup_ctrl_t *lcp, 3807 int pending 3808 ) 3809 { 3810 return (do_dereg(lcp, 0, 0, pending)); 3811 } 3812 3813 /* 3814 * **************************************************************************** 3815 * 3816 * data_sync: 3817 * Synchronize the cache with persistent data store. 3818 * Flush the cache data to data store if the input ec is zero, 3819 * retreat the changes in cache and ignore data store update 3820 * if there is an error. 3821 * 3822 * ec - error code. 3823 * return - error code. 3824 * 3825 * **************************************************************************** 3826 */ 3827 int 3828 data_sync( 3829 int ec 3830 ) 3831 { 3832 /* cache is updated successfully, commit the data to data store */ 3833 if (IS_CACHE_UPDATED()) { 3834 if (ec == 0) { 3835 ec = write_data(DATA_COMMIT, NULL); 3836 } 3837 if (ec == 0) { 3838 /* successful, trigger the SCN */ 3839 (void) queue_msg_set(scn_q, SCN_TRIGGER, (void *)NULL); 3840 } else { 3841 shutdown_server(); 3842 } 3843 } else { 3844 /* ignore all SCNs which have been generated */ 3845 (void) queue_msg_set(scn_q, SCN_IGNORE, (void *)NULL); 3846 3847 (void) write_data(DATA_RETREAT, NULL); 3848 } 3849 3850 return (ec); 3851 } 3852 3853 static pthread_mutex_t name_mtx[3] = { 3854 PTHREAD_MUTEX_INITIALIZER, 3855 PTHREAD_MUTEX_INITIALIZER, 3856 PTHREAD_MUTEX_INITIALIZER 3857 }; 3858 static const char *name_pattern[3] = { 3859 "ENTITY_ID_%d", 3860 "DD_%d", 3861 "DD-Set_%d" 3862 }; 3863 static uint32_t name_count[3] = { 3864 0, 3865 0, 3866 0 3867 }; 3868 3869 /* 3870 * **************************************************************************** 3871 * 3872 * make_unique_name: 3873 * make a default unique name for a newly registered network entity, 3874 * discovery domain or discovery domain set object. 3875 * 3876 * len - pointer of the length of the new name for returning. 3877 * tag - which attribute of the new name is for. 3878 * return - the name being made. 3879 * 3880 * **************************************************************************** 3881 */ 3882 static char * 3883 make_unique_name( 3884 int *len, 3885 uint32_t tag 3886 ) 3887 { 3888 int i; 3889 int count; 3890 char name[32] = { 0 }; 3891 3892 char *p; 3893 3894 lookup_ctrl_t lc; 3895 3896 lc.curr_uid = 0; 3897 3898 switch (tag) { 3899 case ISNS_EID_ATTR_ID: 3900 i = 0; 3901 lc.type = OBJ_ENTITY; 3902 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID); 3903 break; 3904 case ISNS_DD_NAME_ATTR_ID: 3905 i = 1; 3906 lc.type = OBJ_DD; 3907 lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID); 3908 break; 3909 case ISNS_DD_SET_NAME_ATTR_ID: 3910 i = 2; 3911 lc.type = OBJ_DDS; 3912 lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID); 3913 break; 3914 default: 3915 ASSERT(0); 3916 break; 3917 } 3918 3919 lc.op[0] = OP_STRING; 3920 lc.op[1] = 0; 3921 do { 3922 (void) pthread_mutex_lock(&name_mtx[i]); 3923 count = ++ name_count[i]; 3924 (void) pthread_mutex_unlock(&name_mtx[i]); 3925 /* no more space, failure */ 3926 if (count == 0) { 3927 return (NULL); 3928 } 3929 (void) sprintf(name, name_pattern[i], count); 3930 lc.data[0].ptr = (uchar_t *)name; 3931 } while (is_obj_there(&lc) != 0); 3932 3933 /* 4-bytes aligned length */ 3934 *len = strlen(name); 3935 *len = *len + (4 - *len % 4); 3936 p = (char *)malloc(*len); 3937 if (p != NULL) { 3938 (void) strcpy(p, name); 3939 } 3940 return (p); 3941 } 3942 3943 #ifdef DEBUG 3944 void 3945 obj_dump( 3946 void *p 3947 ) 3948 { 3949 print_object(NULL, (isns_obj_t *)p); 3950 } 3951 #endif 3952