1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <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(attr->value.ptr, tmp->len); 1338 } 1339 if (attr->value.ptr != NULL) { 1340 (void) strcpy((char *)attr->value.ptr, 1341 (char *)tmp->value.ptr); 1342 attr->tag = tmp->tag; 1343 attr->len = tmp->len; 1344 } else { 1345 /* memory exhausted */ 1346 return (1); 1347 } 1348 break; 1349 case ISNS_MGMT_IP_ADDR_ATTR_ID: 1350 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1351 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 1352 if (attr->value.ip == NULL) { 1353 attr->value.ip = (in6_addr_t *)calloc(1, tmp->len); 1354 } 1355 if (attr->value.ip != NULL) { 1356 (void) memcpy((void *)attr->value.ip, 1357 (void *)tmp->value.ip, tmp->len); 1358 attr->tag = tmp->tag; 1359 attr->len = tmp->len; 1360 } else { 1361 /* memory exhausted */ 1362 return (1); 1363 } 1364 break; 1365 case ISNS_ENTITY_INDEX_ATTR_ID: 1366 case ISNS_PORTAL_INDEX_ATTR_ID: 1367 case ISNS_ISCSI_NODE_INDEX_ATTR_ID: 1368 case ISNS_PG_INDEX_ATTR_ID: 1369 case ISNS_DD_SET_ID_ATTR_ID: 1370 case ISNS_DD_ID_ATTR_ID: 1371 if (attr->value.ui != 0) { 1372 break; 1373 } 1374 case ISNS_ENTITY_PROTOCOL_ATTR_ID: 1375 case ISNS_VERSION_RANGE_ATTR_ID: 1376 1377 case ISNS_PORTAL_PORT_ATTR_ID: 1378 case ISNS_ESI_PORT_ATTR_ID: 1379 case ISNS_SCN_PORT_ATTR_ID: 1380 1381 case ISNS_ISCSI_NODE_TYPE_ATTR_ID: 1382 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 1383 1384 case ISNS_PG_PORTAL_PORT_ATTR_ID: 1385 case ISNS_PG_TAG_ATTR_ID: 1386 1387 case ISNS_DD_SET_STATUS_ATTR_ID: 1388 case ISNS_DD_ISCSI_INDEX_ATTR_ID: 1389 attr->tag = tmp->tag; 1390 attr->len = tmp->len; 1391 attr->value.ui = tmp->value.ui; 1392 break; 1393 case ISNS_ENTITY_REG_PERIOD_ATTR_ID: 1394 attr->tag = tmp->tag; 1395 attr->len = tmp->len; 1396 attr->value.ui = tmp->value.ui; 1397 t = get_reg_period(); 1398 if (attr->value.ui > t) { 1399 attr->value.ui = t; 1400 } else if (attr->value.ui < ONE_DAY) { 1401 attr->value.ui = ONE_DAY; 1402 } 1403 break; 1404 case ISNS_ESI_INTERVAL_ATTR_ID: 1405 attr->tag = tmp->tag; 1406 attr->len = tmp->len; 1407 attr->value.ui = tmp->value.ui; 1408 if (attr->value.ui > ONE_DAY) { 1409 attr->value.ui = ONE_DAY; 1410 } else if (attr->value.ui < MIN_ESI_INTVAL) { 1411 attr->value.ui = MIN_ESI_INTVAL; /* 20 seconds */ 1412 } 1413 break; 1414 default: 1415 ASSERT(0); 1416 /* don't assign the attribute */ 1417 break; 1418 } 1419 return (0); 1420 } 1421 1422 /* 1423 * **************************************************************************** 1424 * 1425 * copy_attrs: 1426 * copy all of attributes from one object to another. 1427 * 1428 * dst - the destination object. 1429 * tmp - the source object. 1430 * return - error code. 1431 * 1432 * **************************************************************************** 1433 */ 1434 static int 1435 copy_attrs( 1436 isns_obj_t *dst, 1437 const isns_obj_t *src 1438 ) 1439 { 1440 int i = 0; 1441 int n = NUM_OF_ATTRS[dst->type]; 1442 1443 isns_attr_t *dst_attr; 1444 const isns_attr_t *src_attr; 1445 1446 while (i < n) { 1447 src_attr = &(src->attrs[i]); 1448 if (src_attr->tag != 0) { 1449 dst_attr = &(dst->attrs[i]); 1450 if (assign_attr(dst_attr, src_attr) != 0) { 1451 return (1); 1452 } 1453 } 1454 i ++; 1455 } 1456 1457 return (0); 1458 } 1459 1460 /* 1461 * **************************************************************************** 1462 * 1463 * extract_attr: 1464 * extract an attribute from a TLV format data. 1465 * 1466 * attr - the attribute. 1467 * tlv - the TLV format data. 1468 * return - error code. 1469 * 1470 * **************************************************************************** 1471 */ 1472 int 1473 extract_attr( 1474 isns_attr_t *attr, 1475 const isns_tlv_t *tlv, 1476 int flag 1477 ) 1478 { 1479 int ec = 0; 1480 1481 uint32_t min_len = 4, max_len = 224; 1482 1483 switch (tlv->attr_id) { 1484 case ISNS_EID_ATTR_ID: 1485 min_len = 0; 1486 case ISNS_PORTAL_NAME_ATTR_ID: 1487 case ISNS_ISCSI_ALIAS_ATTR_ID: 1488 case ISNS_DD_SET_NAME_ATTR_ID: 1489 case ISNS_DD_NAME_ATTR_ID: 1490 max_len = 256; 1491 case ISNS_ISCSI_NAME_ATTR_ID: 1492 case ISNS_PG_ISCSI_NAME_ATTR_ID: 1493 if (tlv->attr_len < min_len || tlv->attr_len > max_len) { 1494 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1495 } else { 1496 attr->tag = tlv->attr_id; 1497 attr->len = tlv->attr_len; 1498 attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]); 1499 } 1500 break; 1501 case ISNS_ISCSI_AUTH_METHOD_ATTR_ID: 1502 attr->tag = tlv->attr_id; 1503 attr->len = tlv->attr_len; 1504 attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]); 1505 break; 1506 case ISNS_MGMT_IP_ADDR_ATTR_ID: 1507 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1508 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 1509 if (tlv->attr_len != 16) { 1510 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1511 } else { 1512 attr->tag = tlv->attr_id; 1513 attr->len = tlv->attr_len; 1514 attr->value.ip = (void *)&(tlv->attr_value[0]); 1515 } 1516 break; 1517 case ISNS_ENTITY_PROTOCOL_ATTR_ID: 1518 case ISNS_VERSION_RANGE_ATTR_ID: 1519 case ISNS_ENTITY_REG_PERIOD_ATTR_ID: 1520 /* fall throught */ 1521 case ISNS_PORTAL_PORT_ATTR_ID: 1522 case ISNS_ESI_INTERVAL_ATTR_ID: 1523 case ISNS_ESI_PORT_ATTR_ID: 1524 case ISNS_SCN_PORT_ATTR_ID: 1525 /* fall throught */ 1526 case ISNS_ISCSI_NODE_TYPE_ATTR_ID: 1527 /* fall throught */ 1528 case ISNS_PG_PORTAL_PORT_ATTR_ID: 1529 /* fall throught */ 1530 case ISNS_DD_SET_ID_ATTR_ID: 1531 case ISNS_DD_SET_STATUS_ATTR_ID: 1532 /* fall throught */ 1533 case ISNS_DD_ID_ATTR_ID: 1534 if (tlv->attr_len != 4) { 1535 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1536 break; 1537 } 1538 case ISNS_PG_TAG_ATTR_ID: 1539 attr->tag = tlv->attr_id; 1540 attr->len = tlv->attr_len; 1541 if (tlv->attr_len == 4) { 1542 attr->value.ui = ntohl(*(uint32_t *) 1543 &(tlv->attr_value[0])); 1544 } else { 1545 attr->value.ui = 0; 1546 } 1547 break; 1548 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 1549 /* ignore scn bitmap attribute during object registration, */ 1550 /* it is registered by scn_reg message. */ 1551 case ISNS_ENTITY_ISAKMP_P1_ATTR_ID: 1552 case ISNS_ENTITY_CERT_ATTR_ID: 1553 case ISNS_PORTAL_SEC_BMP_ATTR_ID: 1554 case ISNS_PORTAL_ISAKMP_P1_ATTR_ID: 1555 case ISNS_PORTAL_ISAKMP_P2_ATTR_ID: 1556 case ISNS_PORTAL_CERT_ATTR_ID: 1557 break; 1558 case ISNS_PORTAL_INDEX_ATTR_ID: 1559 case ISNS_ISCSI_NODE_INDEX_ATTR_ID: 1560 case ISNS_PG_INDEX_ATTR_ID: 1561 if (flag == 0) { 1562 if (tlv->attr_len != 4) { 1563 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1564 } else { 1565 attr->tag = tlv->attr_id; 1566 attr->len = tlv->attr_len; 1567 attr->value.ui = ntohl(*(uint32_t *) 1568 &(tlv->attr_value[0])); 1569 } 1570 break; 1571 } 1572 case ISNS_ENTITY_INDEX_ATTR_ID: 1573 case ISNS_TIMESTAMP_ATTR_ID: 1574 default: 1575 if (flag == 0) { 1576 ec = ISNS_RSP_INVALID_QRY; 1577 } else { 1578 ec = ISNS_RSP_INVALID_REGIS; 1579 } 1580 break; 1581 } 1582 1583 return (ec); 1584 } 1585 1586 /* 1587 * **************************************************************************** 1588 * 1589 * copy_attr: 1590 * copy an attribute from a TLV format data. 1591 * 1592 * attr - the attribute. 1593 * tlv - the TLV format data. 1594 * return - error code. 1595 * 1596 * **************************************************************************** 1597 */ 1598 static int 1599 copy_attr( 1600 isns_attr_t *attr, 1601 const isns_tlv_t *tlv 1602 ) 1603 { 1604 int ec = 0; 1605 1606 isns_attr_t tmp = { 0 }; 1607 1608 /* extract the attribute first */ 1609 ec = extract_attr(&tmp, tlv, 1); 1610 1611 /* assign the attribute */ 1612 if (ec == 0 && tmp.tag != 0) { 1613 if (assign_attr(attr, &tmp) != 0) { 1614 ec = ISNS_RSP_INTERNAL_ERROR; 1615 } 1616 } 1617 1618 return (ec); 1619 } 1620 1621 /* 1622 * **************************************************************************** 1623 * 1624 * get_timestamp: 1625 * get current timestamp. 1626 * 1627 * return - current timestamp. 1628 * 1629 * **************************************************************************** 1630 */ 1631 uint32_t 1632 get_timestamp( 1633 ) 1634 { 1635 uint32_t t; 1636 int flag; 1637 1638 /* block the scheduler */ 1639 (void) pthread_mutex_lock(&el_mtx); 1640 1641 /* get most current time */ 1642 if (sys_q != NULL) { 1643 /* need to wakeup idle */ 1644 flag = 1; 1645 } else { 1646 flag = 0; 1647 } 1648 t = get_stopwatch(flag); 1649 1650 /* unblock it */ 1651 (void) pthread_mutex_unlock(&el_mtx); 1652 1653 return (t); 1654 } 1655 1656 /* 1657 * **************************************************************************** 1658 * 1659 * get_reg_period: 1660 * get the longest registration period. 1661 * 1662 * return - the longest registration period. 1663 * 1664 * **************************************************************************** 1665 */ 1666 static uint32_t 1667 get_reg_period( 1668 ) 1669 { 1670 uint32_t t; 1671 uint32_t period; 1672 1673 /* get most current time */ 1674 t = get_timestamp(); 1675 1676 /* just one second before the end of the world */ 1677 period = INFINITY - t - 1; 1678 1679 return (period); 1680 } 1681 1682 /* 1683 * **************************************************************************** 1684 * 1685 * obj_calloc: 1686 * allocate memory space for an object. 1687 * 1688 * type - the object type. 1689 * return - pointer of the object being allocated. 1690 * 1691 * **************************************************************************** 1692 */ 1693 isns_obj_t * 1694 obj_calloc( 1695 int type 1696 ) 1697 { 1698 isns_obj_t *obj = NULL; 1699 1700 obj = (isns_obj_t *)calloc(1, SIZEOF_OBJ[type]); 1701 if (obj != NULL) { 1702 obj->type = type; 1703 #ifdef DEBUG 1704 if (verbose_mc) { 1705 printf("object(%d) allocated\n", type); 1706 } 1707 #endif 1708 } 1709 1710 return (obj); 1711 } 1712 1713 /* 1714 * **************************************************************************** 1715 * 1716 * make_default_entity: 1717 * generate a default network entity object. 1718 * 1719 * return - pointer of the default network entity object. 1720 * 1721 * **************************************************************************** 1722 */ 1723 isns_obj_t * 1724 make_default_entity( 1725 ) 1726 { 1727 uint32_t t; 1728 1729 isns_obj_t *obj = obj_calloc(OBJ_ENTITY); 1730 isns_attr_t *attr; 1731 if (obj != NULL) { 1732 int len; 1733 char *eid = make_unique_name(&len, ISNS_EID_ATTR_ID); 1734 if (!eid) { 1735 free(obj); 1736 return (NULL); 1737 } 1738 attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)]; 1739 1740 /* set default entity name */ 1741 attr->tag = ISNS_EID_ATTR_ID; 1742 attr->len = len; 1743 attr->value.ptr = (uchar_t *)eid; 1744 1745 /* set default registration period */ 1746 attr = &obj->attrs[ 1747 ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)]; 1748 if (attr->tag == 0) { 1749 attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID; 1750 attr->len = 4; 1751 t = get_reg_period(); 1752 attr->value.ui = t; 1753 } 1754 } 1755 1756 return (obj); 1757 } 1758 1759 /* 1760 * **************************************************************************** 1761 * 1762 * make_default_pg: 1763 * generate a default portal group object. 1764 * 1765 * iscsi - the iscsi storage node object. 1766 * portal - the portal object. 1767 * return - pointer of the default portal group object. 1768 * 1769 * **************************************************************************** 1770 */ 1771 static isns_obj_t * 1772 make_default_pg( 1773 const isns_obj_t *p1, 1774 const isns_obj_t *p2 1775 ) 1776 { 1777 const isns_obj_t *iscsi, *portal; 1778 const isns_attr_t *name, *addr, *port; 1779 isns_obj_t *pg; 1780 1781 uchar_t *pg_name; 1782 in6_addr_t *pg_addr; 1783 1784 isns_attr_t *attr; 1785 1786 uint32_t *refp; 1787 1788 if (p1->type == OBJ_ISCSI) { 1789 iscsi = p1; 1790 portal = p2; 1791 } else { 1792 iscsi = p2; 1793 portal = p1; 1794 } 1795 name = &iscsi->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)]; 1796 addr = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)]; 1797 port = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)]; 1798 1799 pg = obj_calloc(OBJ_PG); 1800 pg_name = (uchar_t *)malloc(name->len); 1801 pg_addr = (in6_addr_t *)malloc(addr->len); 1802 if (pg != NULL && pg_name != NULL && pg_addr != NULL) { 1803 (void) strcpy((char *)pg_name, (char *)name->value.ptr); 1804 attr = &pg->attrs[ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID)]; 1805 attr->tag = ISNS_PG_ISCSI_NAME_ATTR_ID; 1806 attr->len = name->len; 1807 attr->value.ptr = pg_name; 1808 1809 (void) memcpy((void *)pg_addr, 1810 (void *)addr->value.ip, addr->len); 1811 attr = &pg->attrs[ATTR_INDEX_PG( 1812 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)]; 1813 attr->tag = ISNS_PG_PORTAL_IP_ADDR_ATTR_ID; 1814 attr->len = addr->len; 1815 attr->value.ip = pg_addr; 1816 1817 attr = &pg->attrs[ATTR_INDEX_PG( 1818 ISNS_PG_PORTAL_PORT_ATTR_ID)]; 1819 attr->tag = ISNS_PG_PORTAL_PORT_ATTR_ID; 1820 attr->len = port->len; 1821 attr->value.ui = port->value.ui; 1822 1823 attr = &pg->attrs[ATTR_INDEX_PG( 1824 ISNS_PG_TAG_ATTR_ID)]; 1825 attr->tag = ISNS_PG_TAG_ATTR_ID; 1826 attr->len = 4; 1827 attr->value.ui = ISNS_DEFAULT_PGT; 1828 1829 refp = get_ref_p(pg, OBJ_ISCSI); 1830 *refp = get_obj_uid(iscsi); 1831 1832 refp = get_ref_p(pg, OBJ_PORTAL); 1833 *refp = get_obj_uid(portal); 1834 1835 (void) set_parent_obj(pg, get_parent_uid(iscsi)); 1836 } else { 1837 free(pg); 1838 free(pg_name); 1839 free(pg_addr); 1840 pg = NULL; 1841 } 1842 1843 return (pg); 1844 } 1845 1846 /* 1847 * **************************************************************************** 1848 * 1849 * reg_get_entity: 1850 * parse the Operating Attributes of the DevAttrReg message and 1851 * create the Network Entity object if it has one. 1852 * 1853 * p - the pointer of the object for returning. 1854 * op - the operating attributes. 1855 * op_len - the length of the operating attributes. 1856 * return - error code. 1857 * 1858 * **************************************************************************** 1859 */ 1860 int 1861 reg_get_entity( 1862 isns_obj_t **p, 1863 isns_tlv_t **op, 1864 uint16_t *op_len 1865 ) 1866 { 1867 int ec = 0; 1868 1869 isns_tlv_t *tmp; 1870 uint16_t tmp_len; 1871 isns_attr_t *attr; 1872 1873 isns_obj_t *entity = NULL; 1874 1875 tmp = *op; 1876 tmp_len = *op_len; 1877 1878 /* parse the entity object */ 1879 if (tmp_len >= 8 && IS_ENTITY_KEY(tmp->attr_id)) { 1880 entity = obj_calloc(OBJ_ENTITY); 1881 if (entity != NULL) { 1882 do { 1883 attr = &entity->attrs[ 1884 ATTR_INDEX_ENTITY(tmp->attr_id)]; 1885 ec = copy_attr(attr, tmp); 1886 NEXT_TLV(tmp, tmp_len); 1887 } while (ec == 0 && 1888 tmp_len >= 8 && 1889 IS_ENTITY_ATTR(tmp->attr_id)); 1890 } else { 1891 ec = ISNS_RSP_INTERNAL_ERROR; 1892 } 1893 1894 if (ec == 0) { 1895 /* set default registration period */ 1896 attr = &entity->attrs[ 1897 ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)]; 1898 if (attr->tag == 0) { 1899 attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID; 1900 attr->len = 4; 1901 attr->value.ui = get_reg_period(); 1902 } 1903 } else if (entity != NULL) { 1904 free(entity); 1905 entity = NULL; 1906 } 1907 } 1908 1909 *p = entity; 1910 *op = tmp; 1911 *op_len = tmp_len; 1912 1913 return (ec); 1914 } 1915 1916 /* 1917 * **************************************************************************** 1918 * 1919 * reg_get_iscsi: 1920 * parse the Operating Attributes of the DevAttrReg message and 1921 * create an iSCSI Storage Node object. 1922 * 1923 * p - the pointer of the object for returning. 1924 * pg_key1 - the pointer of iscsi storage node name for returning. 1925 * op - the operating attributes. 1926 * op_len - the length of the operating attributes. 1927 * return - error code. 1928 * 1929 * **************************************************************************** 1930 */ 1931 static int 1932 reg_get_iscsi( 1933 isns_obj_t **p, 1934 isns_attr_t *pg_key1, 1935 isns_tlv_t **op, 1936 uint16_t *op_len 1937 ) 1938 { 1939 int ec = 0; 1940 1941 isns_tlv_t *tmp; 1942 uint16_t tmp_len; 1943 isns_attr_t *attr; 1944 1945 isns_obj_t *obj = NULL; 1946 1947 tmp = *op; 1948 tmp_len = *op_len; 1949 1950 /* keep the iscsi storage node name for */ 1951 /* parsing a pg object which is immediately */ 1952 /* followed with a PGT by the iscsi storage node */ 1953 pg_key1->tag = PG_KEY1; 1954 pg_key1->len = tmp->attr_len; 1955 pg_key1->value.ptr = (uchar_t *)&tmp->attr_value[0]; 1956 1957 /* parse one iscsi storage node object */ 1958 obj = obj_calloc(OBJ_ISCSI); 1959 if (obj != NULL) { 1960 /* parse key & non-key attributes */ 1961 do { 1962 attr = &obj->attrs[ 1963 ATTR_INDEX_ISCSI(tmp->attr_id)]; 1964 ec = copy_attr(attr, tmp); 1965 NEXT_TLV(tmp, tmp_len); 1966 } while (ec == 0 && 1967 tmp_len >= 8 && 1968 IS_ISCSI_ATTR(tmp->attr_id)); 1969 } else { 1970 /* no memory */ 1971 ec = ISNS_RSP_INTERNAL_ERROR; 1972 } 1973 1974 *p = obj; 1975 *op = tmp; 1976 *op_len = tmp_len; 1977 1978 return (ec); 1979 } 1980 1981 /* 1982 * **************************************************************************** 1983 * 1984 * reg_get_portal: 1985 * parse the Operating Attributes of the DevAttrReg message and 1986 * create a Portal object. 1987 * 1988 * p - the pointer of the object for returning. 1989 * pg_key1 - the pointer of portal ip addr for returning. 1990 * pg_key2 - the pointer of portal port for returning. 1991 * op - the operating attributes. 1992 * op_len - the length of the operating attributes. 1993 * return - error code. 1994 * 1995 * **************************************************************************** 1996 */ 1997 static int 1998 reg_get_portal( 1999 isns_obj_t **p, 2000 isns_attr_t *pg_key1, 2001 isns_attr_t *pg_key2, 2002 isns_tlv_t **op, 2003 uint16_t *op_len 2004 ) 2005 { 2006 int ec = 0; 2007 2008 isns_tlv_t *tmp; 2009 uint16_t tmp_len; 2010 isns_attr_t *attr; 2011 2012 isns_obj_t *obj = NULL; 2013 2014 isns_tlv_t *ip; 2015 2016 tmp = *op; 2017 tmp_len = *op_len; 2018 2019 /* keep the portal ip addr */ 2020 pg_key1->tag = PG_KEY2; 2021 pg_key1->len = tmp->attr_len; 2022 pg_key1->value.ip = (void *)&tmp->attr_value[0]; 2023 ip = tmp; 2024 2025 NEXT_TLV(tmp, tmp_len); 2026 if (tmp_len > 8 && 2027 tmp->attr_id == PORTAL_KEY2 && 2028 tmp->attr_len == 4) { 2029 /* keep the portal port */ 2030 pg_key2->tag = PG_KEY3; 2031 pg_key2->len = tmp->attr_len; 2032 pg_key2->value.ui = ntohl(*(uint32_t *)&tmp->attr_value[0]); 2033 2034 /* parse one portal object */ 2035 obj = obj_calloc(OBJ_PORTAL); 2036 if (obj != NULL) { 2037 /* copy ip addr attribute */ 2038 attr = &obj->attrs[ 2039 ATTR_INDEX_PORTAL(ip->attr_id)]; 2040 ec = copy_attr(attr, ip); 2041 /* copy port attribute */ 2042 if (ec == 0) { 2043 attr = &obj->attrs[ 2044 ATTR_INDEX_PORTAL(tmp->attr_id)]; 2045 ec = copy_attr(attr, tmp); 2046 } 2047 /* parse non-key attributes */ 2048 NEXT_TLV(tmp, tmp_len); 2049 while (ec == 0 && 2050 tmp_len >= 8 && 2051 IS_PORTAL_ATTR(tmp->attr_id)) { 2052 attr = &obj->attrs[ 2053 ATTR_INDEX_PORTAL( 2054 tmp->attr_id)]; 2055 ec = copy_attr(attr, tmp); 2056 NEXT_TLV(tmp, tmp_len); 2057 } 2058 } else { 2059 /* no memory */ 2060 ec = ISNS_RSP_INTERNAL_ERROR; 2061 } 2062 } else { 2063 /* ip address is not followed by port */ 2064 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2065 } 2066 2067 *p = obj; 2068 *op = tmp; 2069 *op_len = tmp_len; 2070 2071 return (ec); 2072 } 2073 2074 /* 2075 * **************************************************************************** 2076 * 2077 * reg_get_pg: 2078 * parse the Operating Attributes of the DevAttrReg message and 2079 * create a Portal Group object. 2080 * 2081 * p - the pointer of the object for returning. 2082 * op - the operating attributes. 2083 * op_len - the length of the operating attributes. 2084 * return - error code. 2085 * 2086 * **************************************************************************** 2087 */ 2088 static int 2089 reg_get_pg( 2090 isns_obj_t **p, 2091 isns_tlv_t **op, 2092 uint16_t *op_len 2093 ) 2094 { 2095 int ec = 0; 2096 2097 isns_tlv_t *tmp; 2098 uint16_t tmp_len; 2099 isns_attr_t *attr; 2100 2101 isns_obj_t *obj = NULL; 2102 2103 tmp = *op; 2104 tmp_len = *op_len; 2105 2106 /* parse a complete pg object */ 2107 obj = obj_calloc(OBJ_PG); 2108 if (obj != NULL) { 2109 /* parse attributes */ 2110 do { 2111 attr = &obj->attrs[ 2112 ATTR_INDEX_PG(tmp->attr_id)]; 2113 ec = copy_attr(attr, tmp); 2114 NEXT_TLV(tmp, tmp_len); 2115 } while (ec == 0 && 2116 tmp_len >= 8 && 2117 IS_PG_ATTR(tmp->attr_id)); 2118 } else { 2119 ec = ISNS_RSP_INTERNAL_ERROR; 2120 } 2121 2122 *p = obj; 2123 *op = tmp; 2124 *op_len = tmp_len; 2125 2126 return (ec); 2127 } 2128 2129 /* 2130 * **************************************************************************** 2131 * 2132 * reg_get_pg1: 2133 * parse the Operating Attributes of the DevAttrReg message and 2134 * create a Portal Group object which is followed to a Portal object. 2135 * 2136 * p - the pointer of the object for returning. 2137 * pgt - the size-3 array of pointers which have the pg portal ip addr, port 2138 * and the pg tag attributes. 2139 * op - the operating attributes. 2140 * op_len - the length of the operating attributes. 2141 * return - error code. 2142 * 2143 * **************************************************************************** 2144 */ 2145 static int 2146 reg_get_pg1( 2147 isns_obj_t **p, 2148 isns_attr_t const *pgt, 2149 isns_tlv_t **op, 2150 uint16_t *op_len 2151 ) 2152 { 2153 int ec = 0; 2154 2155 isns_tlv_t *tmp; 2156 uint16_t tmp_len; 2157 isns_attr_t *attr; 2158 2159 isns_obj_t *obj = NULL; 2160 int i = 0; 2161 2162 tmp = *op; 2163 tmp_len = *op_len; 2164 2165 if (pgt[0].tag == PG_KEY2 && 2166 pgt[1].tag == PG_KEY3) { 2167 /* the pg iscsi storage node name is */ 2168 /* followed to a portal group tag */ 2169 obj = obj_calloc(OBJ_PG); 2170 if (obj != NULL) { 2171 /* copy pg iscsi storage node name */ 2172 attr = &obj->attrs[ 2173 ATTR_INDEX_PG(tmp->attr_id)]; 2174 ec = copy_attr(attr, tmp); 2175 /* copy pg ip addr, pg port & pgt */ 2176 while (ec == 0 && i < 3) { 2177 attr = &obj->attrs[ 2178 ATTR_INDEX_PG(pgt[i].tag)]; 2179 ec = assign_attr(attr, &pgt[i]); 2180 i ++; 2181 } 2182 NEXT_TLV(tmp, tmp_len); 2183 } else { 2184 /* no memory */ 2185 ec = ISNS_RSP_INTERNAL_ERROR; 2186 } 2187 } else { 2188 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2189 } 2190 2191 *p = obj; 2192 *op = tmp; 2193 *op_len = tmp_len; 2194 2195 return (ec); 2196 } 2197 2198 /* 2199 * **************************************************************************** 2200 * 2201 * reg_get_pg2: 2202 * parse the Operating Attributes of the DevAttrReg message and 2203 * create a Portal Group object which is followed to a iSCSI 2204 * Storage Node object. 2205 * 2206 * p - the pointer of the object for returning. 2207 * pgt - the size-3 array of pointers which have the pg iscsi storage 2208 * node name and the pg tag attributes. 2209 * op - the operating attributes. 2210 * op_len - the length of the operating attributes. 2211 * return - error code. 2212 * 2213 * **************************************************************************** 2214 */ 2215 static int 2216 reg_get_pg2( 2217 isns_obj_t **p, 2218 isns_attr_t const *pgt, 2219 isns_tlv_t **op, 2220 uint16_t *op_len 2221 ) 2222 { 2223 int ec = 0; 2224 2225 isns_tlv_t *tmp; 2226 uint16_t tmp_len; 2227 isns_attr_t *attr; 2228 2229 isns_obj_t *obj = NULL; 2230 int i = 0; 2231 2232 isns_tlv_t *ip; 2233 2234 tmp = *op; 2235 tmp_len = *op_len; 2236 2237 /* keep ip address */ 2238 ip = tmp; 2239 NEXT_TLV(tmp, tmp_len); 2240 2241 if (tmp_len > 8 && 2242 /* expect pg portal port */ 2243 tmp->attr_id == PG_KEY3 && 2244 tmp->attr_len == 4 && 2245 /* expect pg tag */ 2246 pgt[2].tag == PG_PGT && 2247 /* expect pg iscsi storage node name only */ 2248 pgt[1].tag == 0 && 2249 pgt[0].tag == PG_KEY1) { 2250 /* the pg portal ip addr & port is followed */ 2251 /* to a pg tag and we have the iscsi storage */ 2252 /* node parsed previously */ 2253 obj = obj_calloc(OBJ_PG); 2254 if (obj != NULL) { 2255 /* copy the pg ip addr */ 2256 attr = &obj->attrs[ 2257 ATTR_INDEX_PG(ip->attr_id)]; 2258 ec = copy_attr(attr, ip); 2259 /* copy the pg port */ 2260 if (ec == 0) { 2261 attr = &obj->attrs[ 2262 ATTR_INDEX_PG(tmp->attr_id)]; 2263 ec = copy_attr(attr, tmp); 2264 } 2265 /* copy pg iscsi storage node name & pgt */ 2266 while (ec == 0 && i < 3) { 2267 attr = &obj->attrs[ 2268 ATTR_INDEX_PG(pgt[i].tag)]; 2269 ec = assign_attr(attr, &pgt[i]); 2270 i += 2; 2271 } 2272 NEXT_TLV(tmp, tmp_len); 2273 } else { 2274 ec = ISNS_RSP_INTERNAL_ERROR; 2275 } 2276 } else { 2277 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2278 } 2279 2280 *p = obj; 2281 *op = tmp; 2282 *op_len = tmp_len; 2283 2284 return (ec); 2285 } 2286 2287 /* 2288 * **************************************************************************** 2289 * 2290 * reg_get_obj: 2291 * parse and create one object from the rest of Operating Attributes 2292 * of the DevAttrReg message, the object can be iSCSI Storage Node, 2293 * Portal or Portal Group. 2294 * 2295 * p - the pointer of the object for returning. 2296 * pgt - an attribute array with size 3, the elements are: 2297 * 0: the first pg key attribute, it is either the name of an 2298 * iscsi storage node object or the ip addr of a portal object. 2299 * 1: the second pg key attribute, i.e. the portal port. 2300 * 2: the portal group tag attribute. 2301 * op - the operating attributes. 2302 * op_len - the length of the operating attributes. 2303 * return - error code. 2304 * 2305 * **************************************************************************** 2306 */ 2307 int 2308 reg_get_obj( 2309 isns_obj_t **p, 2310 isns_attr_t *pgt, 2311 isns_tlv_t **op, 2312 uint16_t *op_len 2313 ) 2314 { 2315 int ec = 0; 2316 2317 int derefd = 0; 2318 2319 uint32_t pg_tag; 2320 2321 if (*op_len == 0) { 2322 *p = NULL; 2323 return (0); 2324 } 2325 2326 switch ((*op)->attr_id) { 2327 case ISCSI_KEY: 2328 ec = reg_get_iscsi(p, &pgt[0], op, op_len); 2329 pgt[1].tag = 0; 2330 pgt[2].tag = 0; 2331 break; 2332 case PORTAL_KEY1: 2333 ec = reg_get_portal(p, &pgt[0], &pgt[1], op, op_len); 2334 pgt[2].tag = 0; 2335 break; 2336 case PG_KEY1: 2337 if (pgt[2].tag == PG_PGT) { 2338 /* pg iscsi storage node name is */ 2339 /* followed to a pgt */ 2340 ec = reg_get_pg1(p, pgt, op, op_len); 2341 } else { 2342 /* a complete pg object */ 2343 ec = reg_get_pg(p, op, op_len); 2344 pgt[0].tag = 0; 2345 pgt[1].tag = 0; 2346 pgt[2].tag = 0; 2347 } 2348 break; 2349 case PG_KEY2: 2350 /* pg portal ip addr is followed to a pgt */ 2351 ec = reg_get_pg2(p, pgt, op, op_len); 2352 break; 2353 case PG_PGT: 2354 switch (pgt[0].tag) { 2355 case 0: 2356 /* portal group tag does not follow */ 2357 /* iscsi storage node or portal object */ 2358 *p = NULL; 2359 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2360 break; 2361 case PG_KEY1: 2362 case PG_KEY2: 2363 pgt[2].tag = PG_PGT; 2364 pgt[2].len = (*op)->attr_len; 2365 pg_tag = 0; 2366 switch ((*op)->attr_len) { 2367 case 4: 2368 pg_tag = ntohl(*(uint32_t *) 2369 &(*op)->attr_value[0]); 2370 case 0: 2371 pgt[2].value.ui = pg_tag; 2372 break; 2373 default: 2374 *p = NULL; 2375 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2376 break; 2377 } 2378 if (ec == 0) { 2379 derefd = 1; 2380 NEXT_TLV(*op, *op_len); 2381 ec = reg_get_obj(p, pgt, op, op_len); 2382 } 2383 break; 2384 default: 2385 /* should never happen */ 2386 ASSERT(0); 2387 *p = NULL; 2388 ec = ISNS_RSP_INTERNAL_ERROR; 2389 break; 2390 } 2391 break; 2392 default: 2393 *p = NULL; 2394 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2395 break; 2396 } 2397 2398 if (ec == 0 && derefd == 0) { 2399 ec = update_deref_obj(*p); 2400 } 2401 2402 if (ec != 0 && *p != NULL) { 2403 free_one_object(*p); 2404 *p = NULL; 2405 } 2406 2407 return (ec); 2408 } 2409 2410 /* 2411 * **************************************************************************** 2412 * 2413 * reg_auth_src: 2414 * Authorize the source attribute the DevAttrReg message. 2415 * The update can only performed by the node who has the owenership. 2416 * 2417 * p - the pointer of the object for returning. 2418 * pgt - an attribute array with size 3, the elements are: 2419 * 0: the first pg key attribute, it is either the name of an 2420 * iscsi storage node object or the ip addr of a portal object. 2421 * 1: the second pg key attribute, i.e. the portal port. 2422 * 2: the portal group tag attribute. 2423 * op - the operating attributes. 2424 * op_len - the length of the operating attributes. 2425 * return - error code. 2426 * 2427 * **************************************************************************** 2428 */ 2429 int 2430 reg_auth_src( 2431 isns_type_t type, 2432 uint32_t uid, 2433 uchar_t *src 2434 ) 2435 { 2436 lookup_ctrl_t lc; 2437 uint32_t puid; 2438 2439 puid = is_parent_there(src); 2440 2441 if (TYPE_OF_PARENT[type] != 0) { 2442 SET_UID_LCP(&lc, type, uid); 2443 uid = cache_lookup(&lc, NULL, cb_get_parent); 2444 type = TYPE_OF_PARENT[type]; 2445 } 2446 2447 if (uid != 0 && puid == 0) { 2448 SET_UID_LCP(&lc, type, uid); 2449 uid = cache_lookup(&lc, NULL, cb_node_child); 2450 } 2451 2452 if (puid != uid) { 2453 return (0); 2454 } 2455 2456 return (1); 2457 } 2458 2459 /* 2460 * **************************************************************************** 2461 * 2462 * is_obj_online: 2463 * determine if the object is currently registered with the server. 2464 * 2465 * obj - the object being checked. 2466 * return - 0: not registered, otherwise registered. 2467 * 2468 * **************************************************************************** 2469 */ 2470 int 2471 is_obj_online( 2472 const isns_obj_t *obj 2473 ) 2474 { 2475 int online = 1; 2476 2477 switch (obj->type) { 2478 case OBJ_ISCSI: 2479 online = obj->attrs[ATTR_INDEX_ISCSI( 2480 ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui == 0 ? 0 : 1; 2481 break; 2482 default: 2483 break; 2484 } 2485 2486 return (online); 2487 } 2488 2489 static int 2490 set_obj_offline( 2491 isns_obj_t *obj 2492 ) 2493 { 2494 switch (obj->type) { 2495 case OBJ_ISCSI: 2496 obj->attrs[ATTR_INDEX_ISCSI( 2497 ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui = 0; 2498 break; 2499 default: 2500 break; 2501 } 2502 2503 return (0); 2504 } 2505 2506 /* 2507 * **************************************************************************** 2508 * 2509 * assoc_clone: 2510 * clone the association object. 2511 * 2512 * p - the object being cloned. 2513 * clone_flag - 0: the object is being removed; 2514 * 1: only the association is being removed. 2515 * return - the clone object. 2516 * 2517 * **************************************************************************** 2518 */ 2519 void * 2520 assoc_clone( 2521 void *p, 2522 int clone_flag 2523 ) 2524 { 2525 isns_type_t type; 2526 isns_obj_t *clone; 2527 const isns_attr_t *src_attr; 2528 isns_attr_t *dst_attr; 2529 uint32_t id, op; 2530 int i = 0; 2531 2532 const isns_obj_t *obj; 2533 uint32_t dd_flag; 2534 int online; 2535 2536 int state; 2537 2538 obj = (isns_obj_t *)p; 2539 2540 if (obj->type != OBJ_ISCSI) { 2541 return (NULL); 2542 } 2543 2544 dd_flag = (get_dd_id(get_obj_uid(obj), ISNS_DEFAULT_DD_ID) == 0) ? 2545 0 : 1; 2546 online = is_obj_online(obj); 2547 2548 state = (clone_flag << 2) | (dd_flag << 1) | online; 2549 2550 /* clone_flag dd_flag online action */ 2551 /* 0 0 0 ASSERT(0) */ 2552 /* 0 0 1 NULL */ 2553 /* 0 1 0 itself */ 2554 /* 0 1 1 clone it */ 2555 /* 1 0 0 NULL */ 2556 /* 1 0 1 itself */ 2557 /* 1 1 0 itself */ 2558 /* 1 1 1 itself */ 2559 2560 switch (state) { 2561 case 0: 2562 ASSERT(0); 2563 case 1: 2564 case 4: 2565 return (NULL); 2566 case 2: 2567 case 5: 2568 case 6: 2569 case 7: 2570 return (p); 2571 case 3: 2572 default: 2573 break; 2574 } 2575 2576 type = obj->type; 2577 clone = obj_calloc(type); 2578 2579 if (clone != NULL) { 2580 id = UID_ATTR_INDEX[type]; 2581 src_attr = &(obj->attrs[id]); 2582 dst_attr = &(clone->attrs[id]); 2583 if (assign_attr(dst_attr, src_attr) != 0) { 2584 free_one_object(clone); 2585 return (NULL); 2586 } 2587 2588 while (i < MAX_KEY_ATTRS) { 2589 op = KEY_ATTR_OP[type][i]; 2590 if (op != 0) { 2591 id = KEY_ATTR_INDEX[type][i]; 2592 src_attr = &(obj->attrs[id]); 2593 dst_attr = &(clone->attrs[id]); 2594 if (assign_attr(dst_attr, src_attr) != 0) { 2595 free_one_object(clone); 2596 return (NULL); 2597 } 2598 } else { 2599 break; 2600 } 2601 i ++; 2602 } 2603 } 2604 2605 return ((void *)clone); 2606 } 2607 2608 /* 2609 * **************************************************************************** 2610 * 2611 * free_one_object: 2612 * free up one object. 2613 * 2614 * obj - the object being freed. 2615 * 2616 * **************************************************************************** 2617 */ 2618 void 2619 free_one_object( 2620 isns_obj_t *obj 2621 ) 2622 { 2623 int i; 2624 uint32_t *cuid; 2625 if (obj == NULL) { 2626 return; 2627 } 2628 for (i = 0; i < NUM_OF_ATTRS[obj->type]; i++) { 2629 isns_attr_t *attr = &obj->attrs[i]; 2630 switch (attr->tag) { 2631 case ISNS_EID_ATTR_ID: 2632 case ISNS_ISCSI_NAME_ATTR_ID: 2633 case ISNS_ISCSI_ALIAS_ATTR_ID: 2634 case ISNS_ISCSI_AUTH_METHOD_ATTR_ID: 2635 case ISNS_PG_ISCSI_NAME_ATTR_ID: 2636 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 2637 case ISNS_PORTAL_NAME_ATTR_ID: 2638 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 2639 case ISNS_DD_SET_NAME_ATTR_ID: 2640 case ISNS_DD_NAME_ATTR_ID: 2641 case ISNS_DD_ISCSI_NAME_ATTR_ID: 2642 case ISNS_DD_FC_PORT_NAME_ATTR_ID: 2643 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID: 2644 #ifdef DEBUG 2645 if (verbose_mc) { 2646 printf("memory(%d) deallocated\n", 2647 attr->len); 2648 } 2649 #endif 2650 free(attr->value.ptr); 2651 attr->value.ptr = NULL; 2652 break; 2653 default: 2654 break; 2655 } 2656 } 2657 2658 /* free child uids */ 2659 i = 0; 2660 while (i < NUM_OF_CHILD[obj->type]) { 2661 cuid = get_child_n(obj, i); 2662 free(cuid); 2663 i ++; 2664 } 2665 2666 /* at last, free the object itself */ 2667 #ifdef DEBUG 2668 if (verbose_mc) { 2669 printf("object(%d) deallocated\n", obj->type); 2670 } 2671 #endif 2672 free(obj); 2673 } 2674 2675 /* 2676 * **************************************************************************** 2677 * 2678 * free_object: 2679 * free up one object. 2680 * 2681 * obj - the object being freed. 2682 * 2683 * **************************************************************************** 2684 */ 2685 void 2686 free_object( 2687 isns_obj_t *obj 2688 ) 2689 { 2690 free_one_object(obj); 2691 } 2692 2693 /* 2694 * **************************************************************************** 2695 * 2696 * set_parent_obj: 2697 * set the parent object UID. 2698 * 2699 * obj - the child object. 2700 * puid- the parent object UID. 2701 * return - error code. 2702 * 2703 * **************************************************************************** 2704 */ 2705 int 2706 set_parent_obj( 2707 isns_obj_t *obj, 2708 uint32_t puid 2709 ) 2710 { 2711 uint32_t *const p = get_parent_p(obj); 2712 if (p != NULL) { 2713 *p = puid; 2714 } 2715 2716 return (0); 2717 } 2718 2719 /* 2720 * **************************************************************************** 2721 * 2722 * buff_child_obj: 2723 * add a child object UID to the child object array. 2724 * 2725 * obj - the parent object. 2726 * child_type - the type of the child object. 2727 * number - the number of the child object. 2728 * return - the length of the child object UID array. 2729 * 2730 * **************************************************************************** 2731 */ 2732 int 2733 buff_child_obj( 2734 const isns_type_t ptype, 2735 const isns_type_t ctype, 2736 const void *c, 2737 void const ***child 2738 ) 2739 { 2740 int ec = 0; 2741 2742 int i = 0; 2743 void const ***pp, **p; 2744 uint32_t num, new_num; 2745 2746 pp = NULL; 2747 /* get the pointer of the array which the child belongs to */ 2748 while (i < NUM_OF_CHILD[ptype]) { 2749 if (TYPE_OF_CHILD[ptype][i] == ctype) { 2750 pp = &child[i]; 2751 break; 2752 } 2753 i ++; 2754 } 2755 2756 /* the child type is not applicable */ 2757 if (pp == NULL) { 2758 return (ec); 2759 } 2760 2761 p = *pp; 2762 /* get an empty slot from the uid array for this child */ 2763 if (p != NULL) { 2764 num = (uint32_t)*p; 2765 i = 0; 2766 while (i < num) { 2767 if (p[++i] == NULL) { 2768 /* found it */ 2769 p[i] = c; 2770 return (ec); 2771 } 2772 } 2773 p = *pp; 2774 new_num = num + 1; 2775 } else { 2776 num = 0; 2777 new_num = 1; 2778 } 2779 2780 /* the array is full, enlarge the child uid array */ 2781 p = (void const **)realloc(p, (new_num + 1) * sizeof (void *)); 2782 if (p != NULL) { 2783 *pp = p; 2784 *p = (void *)new_num; 2785 p[new_num] = c; 2786 } else { 2787 ec = ISNS_RSP_INTERNAL_ERROR; 2788 } 2789 2790 return (ec); 2791 } 2792 2793 /* 2794 * **************************************************************************** 2795 * 2796 * update_child_object: 2797 * update the child object of a network entity object. 2798 * 2799 * puid - the UID of the parent object, i.e. the network entity object. 2800 * child_type - the type of the child object. 2801 * child_uid - the uid of the child object. 2802 * return - error code. 2803 * 2804 * **************************************************************************** 2805 */ 2806 int 2807 update_child_obj( 2808 const isns_type_t ptype, 2809 const uint32_t puid, 2810 void const ***child, 2811 int child_flag 2812 ) 2813 { 2814 int ec = 0; 2815 2816 lookup_ctrl_t lc; 2817 2818 SET_UID_LCP(&lc, ptype, puid); 2819 2820 lc.data[1].ptr = (uchar_t *)child; 2821 lc.data[2].ui = child_flag; 2822 2823 ec = cache_lookup(&lc, NULL, cb_add_child); 2824 2825 return (ec); 2826 } 2827 2828 int 2829 update_ref_obj( 2830 const isns_obj_t *obj 2831 ) 2832 { 2833 uint32_t uid; 2834 lookup_ctrl_t lc; 2835 isns_type_t t; 2836 2837 t = obj->type; 2838 2839 if (TYPE_OF_REF[t][0] != 0) { 2840 (void) setup_ref_lcp(&lc, obj, NULL); 2841 2842 lc.id[2] = t; 2843 lc.data[2].ui = get_obj_uid(obj); 2844 2845 uid = 0; 2846 do { 2847 lc.curr_uid = uid; 2848 (void) cache_lookup(&lc, &uid, cb_set_ref); 2849 } while (uid != 0); 2850 } 2851 2852 return (0); 2853 } 2854 2855 /* 2856 * **************************************************************************** 2857 * 2858 * verify_ref_obj: 2859 * update the reference bit of a portal group object. 2860 * 2861 * obj - the object being ref'ed. 2862 * return - error code. 2863 * 2864 * **************************************************************************** 2865 */ 2866 int 2867 verify_ref_obj( 2868 const isns_type_t ptype, 2869 const uint32_t puid, 2870 void const ***child 2871 ) 2872 { 2873 int ec = 0; 2874 2875 lookup_ctrl_t lc; 2876 2877 SET_UID_LCP(&lc, ptype, puid); 2878 2879 lc.data[1].ptr = (uchar_t *)child; 2880 2881 ec = cache_lookup(&lc, NULL, cb_verify_ref); 2882 2883 return (ec); 2884 } 2885 2886 int 2887 update_deref_obj( 2888 isns_obj_t *obj 2889 ) 2890 { 2891 int ec = 0; 2892 2893 isns_type_t t, rt; 2894 lookup_ctrl_t lc; 2895 int i, ref_count; 2896 2897 uint32_t uid, *refp; 2898 2899 t = obj->type; 2900 i = ref_count = 0; 2901 while (i < NUM_OF_REF[t]) { 2902 rt = TYPE_OF_REF[t][i + 1]; 2903 (void) setup_deref_lcp(&lc, obj, rt); 2904 uid = is_obj_there(&lc); 2905 if (uid != 0) { 2906 refp = get_ref_p(obj, lc.type); 2907 *refp = uid; 2908 ref_count ++; 2909 } 2910 i ++; 2911 } 2912 2913 if (i > 0 && ref_count == 0) { 2914 ec = ISNS_RSP_INVALID_REGIS; 2915 } 2916 2917 return (ec); 2918 } 2919 2920 /* 2921 * **************************************************************************** 2922 * 2923 * register_object: 2924 * add one object to the object container. 2925 * 2926 * obj - the object being added. 2927 * uid_p- the pointer for returning object UID. 2928 * update_p- the pointer for returning flag which indicates if the object 2929 * is newly registered or updated with an existing one. 2930 * return - error code. 2931 * 2932 * **************************************************************************** 2933 */ 2934 int 2935 register_object( 2936 isns_obj_t *obj, 2937 uint32_t *uid_p, 2938 int *update_p 2939 ) 2940 { 2941 return (cache_add(obj, 0, uid_p, update_p)); 2942 } 2943 2944 /* 2945 * **************************************************************************** 2946 * 2947 * register_assoc: 2948 * add one association object to the object container, the association 2949 * object has only the information for discovery domain membership, i.e. 2950 * a name and UID only. 2951 * 2952 * obj - the association object being added. 2953 * uid_p- the pointer for returning object UID. 2954 * return - error code. 2955 * 2956 * **************************************************************************** 2957 */ 2958 int 2959 register_assoc( 2960 isns_obj_t *obj, 2961 uint32_t *uid_p 2962 ) 2963 { 2964 return (cache_add(obj, 1, uid_p, NULL)); 2965 } 2966 2967 /* 2968 * **************************************************************************** 2969 * 2970 * is_obj_there: 2971 * check if the object is registered or not. 2972 * 2973 * lcp - the lookup control data. 2974 * return - the object UID. 2975 * 2976 * **************************************************************************** 2977 */ 2978 uint32_t 2979 is_obj_there( 2980 lookup_ctrl_t *lcp 2981 ) 2982 { 2983 uint32_t uid; 2984 2985 (void) cache_lookup(lcp, &uid, NULL); 2986 2987 return (uid); 2988 } 2989 2990 uint32_t 2991 is_parent_there( 2992 uchar_t *src 2993 ) 2994 { 2995 lookup_ctrl_t lc; 2996 2997 lc.curr_uid = 0; 2998 lc.type = OBJ_ISCSI; 2999 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 3000 lc.op[0] = OP_STRING; 3001 lc.data[0].ptr = src; 3002 lc.op[1] = 0; 3003 3004 return (cache_lookup(&lc, NULL, cb_get_parent)); 3005 } 3006 3007 /* 3008 * **************************************************************************** 3009 * 3010 * setup_ref_lcp: 3011 * prepare the lookup control data for looking up a portal group 3012 * object which references to a iscsi stroage node and/or a portal 3013 * object. 3014 * 3015 * lcp - the lookup control data. 3016 * iscsi- the ref'ed iscsi storage node object. 3017 * portal- the ref'ed portal object. 3018 * return - error code. 3019 * 3020 * **************************************************************************** 3021 */ 3022 static int 3023 setup_ref_lcp( 3024 lookup_ctrl_t *lcp, 3025 const isns_obj_t *iscsi, 3026 const isns_obj_t *portal 3027 ) 3028 { 3029 int i = 0, j = 0; 3030 3031 lcp->curr_uid = 0; 3032 lcp->type = TYPE_OF_REF[iscsi->type][0]; 3033 3034 /* extrace the matching attributes from iscsi storage node object */ 3035 while (iscsi != NULL && 3036 i < MAX_REF_MATCH && 3037 REF_MATCH_OPS[iscsi->type][i] > 0) { 3038 lcp->id[i] = REF_MATCH_ID2[iscsi->type][i]; 3039 lcp->op[i] = REF_MATCH_OPS[iscsi->type][i]; 3040 lcp->data[i].ptr = iscsi->attrs[ 3041 REF_MATCH_ID1[iscsi->type][i]].value.ptr; 3042 i ++; 3043 } 3044 3045 /* extrace the matching attributes from portal object */ 3046 while (portal != NULL && 3047 i < MAX_LOOKUP_CTRL && 3048 j < MAX_REF_MATCH && 3049 REF_MATCH_OPS[portal->type][j] > 0) { 3050 lcp->id[i] = REF_MATCH_ID2[portal->type][j]; 3051 lcp->op[i] = REF_MATCH_OPS[portal->type][j]; 3052 lcp->data[i].ptr = portal->attrs[ 3053 REF_MATCH_ID1[portal->type][j]].value.ptr; 3054 j ++; 3055 i ++; 3056 } 3057 3058 if (i < MAX_LOOKUP_CTRL) { 3059 lcp->op[i] = 0; 3060 } 3061 3062 return (0); 3063 } 3064 3065 static int 3066 setup_deref_lcp( 3067 lookup_ctrl_t *lcp, 3068 const isns_obj_t *pg, 3069 isns_type_t t 3070 ) 3071 { 3072 int i = 0; 3073 3074 lcp->curr_uid = 0; 3075 lcp->type = t; 3076 3077 /* extrace the matching attributes from iscsi storage node object */ 3078 while (i < MAX_REF_MATCH && 3079 REF_MATCH_OPS[t][i] > 0) { 3080 lcp->id[i] = REF_MATCH_ID1[t][i]; 3081 lcp->op[i] = REF_MATCH_OPS[t][i]; 3082 lcp->data[i].ptr = pg->attrs[ 3083 REF_MATCH_ID2[t][i]].value.ptr; 3084 i ++; 3085 } 3086 3087 if (i < MAX_LOOKUP_CTRL) { 3088 lcp->op[i] = 0; 3089 } 3090 3091 return (0); 3092 } 3093 3094 /* 3095 * **************************************************************************** 3096 * 3097 * setup_parent_lcp: 3098 * prepare the lookup control data for looking up parent object 3099 * with a child object. 3100 * 3101 * lcp - the lookup control data. 3102 * obj - the child object. 3103 * return - parent object UID. 3104 * 3105 * **************************************************************************** 3106 */ 3107 static uint32_t 3108 setup_parent_lcp( 3109 lookup_ctrl_t *lcp, 3110 isns_obj_t *obj 3111 ) 3112 { 3113 isns_type_t ptype; 3114 uint32_t puid; 3115 3116 puid = get_parent_uid(obj); 3117 if (puid != 0) { 3118 ptype = TYPE_OF_PARENT[obj->type]; 3119 SET_UID_LCP(lcp, ptype, puid); 3120 lcp->data[1].ui = obj->type; 3121 lcp->data[2].ui = get_obj_uid(obj); 3122 } 3123 3124 return (puid); 3125 } 3126 3127 static int 3128 cb_get_parent( 3129 void *p1, 3130 /* LINTED E_FUNC_ARG_UNUSED */ 3131 void *p2 3132 ) 3133 { 3134 return (get_parent_uid(p1)); 3135 } 3136 3137 static int 3138 cb_node_child( 3139 void *p1, 3140 /* LINTED E_FUNC_ARG_UNUSED */ 3141 void *p2 3142 ) 3143 { 3144 isns_obj_t *obj = (isns_obj_t *)p1; 3145 3146 uint32_t num, uid; 3147 3148 uint32_t *cuid = get_child_t(obj, OBJ_ISCSI); 3149 3150 if (cuid != NULL) { 3151 num = *cuid; 3152 } else { 3153 num = 0; 3154 } 3155 3156 while (num > 0) { 3157 uid = *++cuid; 3158 if (uid != 0) { 3159 return (uid); 3160 } 3161 num --; 3162 } 3163 3164 return (0); 3165 } 3166 3167 /* 3168 * **************************************************************************** 3169 * 3170 * cb_set_ref: 3171 * callback function which sets the reference bit to 1 according to 3172 * the type of object. 3173 * 3174 * p1 - the object. 3175 * p2 - the lcp. 3176 * return - error code. 3177 * 3178 * **************************************************************************** 3179 */ 3180 static int 3181 cb_set_ref( 3182 void *p1, 3183 void *p2 3184 ) 3185 { 3186 isns_obj_t *obj = (isns_obj_t *)p1; 3187 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3188 3189 isns_type_t t; 3190 uint32_t u; 3191 3192 uint32_t *refp; 3193 3194 t = lcp->id[2]; 3195 u = lcp->data[2].ui; 3196 refp = get_ref_p(obj, t); 3197 *refp = u; 3198 3199 /* successful */ 3200 return (0); 3201 } 3202 3203 /* 3204 * **************************************************************************** 3205 * 3206 * cb_clear_ref: 3207 * callback function which clears the reference bit according to 3208 * the type of object. 3209 * 3210 * p1 - the object. 3211 * p2 - the lcp. 3212 * return - 1: the object is no longer ref'ed, 0: otherwise. 3213 * 3214 * **************************************************************************** 3215 */ 3216 static int 3217 cb_clear_ref( 3218 void *p1, 3219 void *p2 3220 ) 3221 { 3222 isns_obj_t *obj = (isns_obj_t *)p1; 3223 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3224 3225 isns_type_t t; 3226 uint32_t *refp; 3227 3228 int i = 0; 3229 uint32_t ref; 3230 3231 t = lcp->data[2].ui; 3232 refp = get_ref_p(obj, t); 3233 *refp = 0; 3234 3235 while (i < NUM_OF_REF[obj->type]) { 3236 ref = get_ref_n(obj, i); 3237 if (ref != 0) { 3238 return (0); 3239 } 3240 i ++; 3241 } 3242 3243 return (1); 3244 } 3245 3246 static int 3247 cb_add_child( 3248 void *p1, 3249 void *p2 3250 ) 3251 { 3252 isns_obj_t *obj = (isns_obj_t *)p1; 3253 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3254 3255 const void ***child; 3256 const void **vpp; 3257 uint32_t vnum; 3258 int child_flag; 3259 3260 uint32_t **upp, *up; 3261 uint32_t num; 3262 3263 isns_obj_t *o; 3264 3265 int i = 0; 3266 3267 child = (const void ***)lcp->data[1].ptr; 3268 child_flag = lcp->data[2].ui; 3269 3270 while (i < NUM_OF_CHILD[obj->type]) { 3271 vpp = child[i]; 3272 if (vpp != NULL && 3273 (vnum = (uint32_t)*vpp) > 0 && 3274 *(vpp + 1) != NULL) { 3275 upp = get_child_np(obj, i); 3276 if (*upp == NULL) { 3277 if (child_flag == 0 && 3278 sizeof (typeof (**upp)) == 3279 sizeof (typeof (**child))) { 3280 *upp = (uint32_t *)vpp; 3281 vpp = NULL; 3282 child[i] = NULL; 3283 } 3284 num = vnum; 3285 } else { 3286 num = **upp + vnum; 3287 } 3288 if (vpp != NULL) { 3289 /* copy required */ 3290 up = (uint32_t *)realloc(*upp, 3291 (num + 1) * sizeof (uint32_t)); 3292 if (up == NULL) { 3293 return (ISNS_RSP_INTERNAL_ERROR); 3294 } 3295 *upp = up; 3296 *up = num; 3297 up += num; 3298 vpp += vnum; 3299 while (vnum > 0) { 3300 if (*vpp == NULL) { 3301 *up = 0; 3302 } else if (child_flag == 0) { 3303 *up = (uint32_t)*vpp; 3304 *vpp = NULL; 3305 } else { 3306 o = (isns_obj_t *)*vpp; 3307 *up = get_obj_uid(o); 3308 if (is_obj_online(o) == 0) { 3309 free_object(o); 3310 } 3311 *vpp = NULL; 3312 } 3313 up --; 3314 vpp --; 3315 vnum --; 3316 } 3317 } 3318 } 3319 i ++; 3320 } 3321 3322 return (0); 3323 } 3324 3325 /* 3326 * **************************************************************************** 3327 * 3328 * cb_remove_child: 3329 * callback function which removes a child object UID from the 3330 * children objet UID array of the parent object. 3331 * 3332 * p1 - the object. 3333 * p2 - the lcp. 3334 * return - 1: no more such type of child object, 0: otherwise. 3335 * 3336 * **************************************************************************** 3337 */ 3338 static int 3339 cb_remove_child( 3340 void *p1, 3341 void *p2 3342 ) 3343 { 3344 isns_obj_t *obj = (isns_obj_t *)p1; 3345 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3346 uint32_t child_type = lcp->data[1].ui; 3347 uint32_t child_uid = lcp->data[2].ui; 3348 uint32_t *cuidp, cuid, num_of_child = 0; 3349 int i; 3350 3351 /* get the children object UID array */ 3352 cuidp = get_child_t(obj, child_type); 3353 if (cuidp != NULL) { 3354 num_of_child = *cuidp; 3355 } 3356 3357 /* remove it */ 3358 while (num_of_child > 0) { 3359 cuid = *++cuidp; 3360 if (cuid == child_uid) { 3361 *cuidp = 0; 3362 break; 3363 } 3364 num_of_child --; 3365 } 3366 3367 /* check if all of child object UIDs are removed */ 3368 i = 0; 3369 while (i < NUM_OF_CHILD[obj->type]) { 3370 cuidp = get_child_n(obj, i); 3371 if (cuidp != NULL) { 3372 num_of_child = *cuidp; 3373 while (num_of_child > 0) { 3374 cuid = *++cuidp; 3375 if (cuid != 0) { 3376 return (0); 3377 } 3378 num_of_child --; 3379 } 3380 } 3381 i ++; 3382 } 3383 3384 return (1); 3385 } 3386 3387 static int 3388 cb_verify_ref( 3389 void *p1, 3390 void *p2 3391 ) 3392 { 3393 int ec = 0; 3394 3395 isns_obj_t *parent = (isns_obj_t *)p1; 3396 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3397 3398 const void ***child; 3399 3400 const void **vpp; 3401 const void *vp; 3402 uint32_t vnum; 3403 3404 const void **evpp; 3405 const void *evp; 3406 uint32_t evnum; 3407 3408 isns_type_t pt; /* parent object type */ 3409 isns_type_t ct; /* child object type */ 3410 isns_type_t rt; /* ref object type */ 3411 isns_type_t et; /* peer object type */ 3412 3413 uint32_t *up; 3414 uint32_t u; 3415 uint32_t unum; 3416 3417 lookup_ctrl_t lc; 3418 uint8_t flag[MAX_OBJ_TYPE + 1] = { 0 }; 3419 3420 int i, j, k; 3421 3422 pt = parent->type; 3423 3424 child = (const void ***)lcp->data[1].ptr; 3425 3426 for (i = 0; i < NUM_OF_CHILD[pt]; i++) { 3427 ct = TYPE_OF_CHILD[pt][i]; 3428 rt = TYPE_OF_REF[ct][0]; 3429 if (rt == 0) { 3430 continue; 3431 } 3432 3433 et = TYPE_OF_REF[ct][1]; 3434 vpp = child[i]; 3435 if (vpp != NULL) { 3436 vnum = (uint32_t)*vpp; 3437 up = get_child_t(parent, et); 3438 if (up != NULL) { 3439 unum = *up; 3440 } else { 3441 unum = 0; 3442 } 3443 } else { 3444 vnum = 0; 3445 } 3446 3447 j = vnum; 3448 while (j > 0) { 3449 vp = vpp[j]; 3450 if (vp != NULL) { 3451 (void) setup_ref_lcp(&lc, vp, NULL); 3452 k = unum; 3453 while (k > 0) { 3454 u = up[k]; 3455 if (u != 0) { 3456 ec = ref_new2old( 3457 &lc, et, u, vp); 3458 if (ec != 0) { 3459 return (ec); 3460 } 3461 } 3462 k --; 3463 } /* End of while each unum */ 3464 } 3465 j --; 3466 } /* End of while each vnum */ 3467 3468 if (flag[ct] != 0) { 3469 continue; 3470 } 3471 3472 evnum = 0; 3473 j = 0; 3474 while (j < NUM_OF_CHILD[pt]) { 3475 if (TYPE_OF_CHILD[pt][j] == et) { 3476 evpp = child[j]; 3477 if (evpp != NULL) { 3478 evnum = (uint32_t)*evpp; 3479 } 3480 break; 3481 } 3482 j ++; 3483 } 3484 3485 j = vnum; 3486 while (j > 0) { 3487 vp = vpp[j]; 3488 k = evnum; 3489 while (k > 0) { 3490 evp = evpp[k]; 3491 if (vp != NULL && evp != NULL) { 3492 (void) setup_ref_lcp(&lc, vp, evp); 3493 ec = ref_new2new(&lc, vp, evp); 3494 if (ec != 0) { 3495 return (ec); 3496 } 3497 } 3498 k --; 3499 } 3500 j --; 3501 } /* End of while each vnum */ 3502 3503 flag[et] = 1; 3504 } /* End of for each type of child */ 3505 3506 return (ec); 3507 } 3508 3509 static int 3510 cb_ref_new2old( 3511 void *p1, 3512 void *p2 3513 ) 3514 { 3515 isns_obj_t *obj = (isns_obj_t *)p1; 3516 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3517 3518 isns_type_t et; 3519 uint32_t uu; 3520 3521 uint32_t ref; 3522 3523 int match; 3524 3525 et = lcp->id[2]; 3526 uu = lcp->data[2].ui; 3527 3528 ref = get_ref_t(obj, et); 3529 3530 if (ref == uu) { 3531 match = 1; 3532 } else { 3533 match = 0; 3534 } 3535 3536 return (match); 3537 } 3538 3539 static int 3540 cb_new_ref( 3541 void *p1, 3542 void *p2 3543 ) 3544 { 3545 int ec = 0; 3546 3547 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 3548 isns_obj_t *a = (isns_obj_t *)p1; 3549 isns_obj_t *b = (isns_obj_t *)lcp->data[2].ptr; 3550 3551 ec = new_ref(a, b); 3552 3553 return (ec); 3554 } 3555 3556 static int 3557 ref_new2old( 3558 lookup_ctrl_t *lcp, 3559 isns_type_t et, 3560 uint32_t uu, 3561 const isns_obj_t *vp 3562 ) 3563 { 3564 int ec = 0; 3565 3566 int match; 3567 uint32_t uid; 3568 3569 lookup_ctrl_t lc; 3570 3571 lcp->id[2] = et; 3572 lcp->data[2].ui = uu; 3573 3574 uid = 0; 3575 do { 3576 lcp->curr_uid = uid; 3577 match = cache_lookup(lcp, &uid, cb_ref_new2old); 3578 } while (match == 0 && uid != 0); 3579 3580 if (match == 0) { 3581 /* no such ref, create a default one */ 3582 SET_UID_LCP(&lc, et, uu); 3583 3584 lc.data[2].ptr = (uchar_t *)vp; 3585 3586 ec = cache_lookup(&lc, NULL, cb_new_ref); 3587 } 3588 3589 return (ec); 3590 } 3591 3592 static int 3593 ref_new2new( 3594 lookup_ctrl_t *lcp, 3595 const isns_obj_t *p1, 3596 const isns_obj_t *p2 3597 ) 3598 { 3599 int ec = 0; 3600 3601 if (is_obj_there(lcp) != 0) { 3602 return (0); 3603 } 3604 3605 ec = new_ref(p1, p2); 3606 3607 return (ec); 3608 } 3609 3610 static int 3611 new_ref( 3612 const isns_obj_t *p1, 3613 const isns_obj_t *p2 3614 ) 3615 { 3616 int ec = 0; 3617 3618 isns_obj_t *obj; 3619 3620 obj = make_ref[p1->type](p1, p2); 3621 if (obj != NULL) { 3622 ec = register_object(obj, NULL, NULL); 3623 } else { 3624 ec = ISNS_RSP_INTERNAL_ERROR; 3625 } 3626 3627 return (ec); 3628 } 3629 3630 /* 3631 * **************************************************************************** 3632 * 3633 * do_dereg: 3634 * Physically remove an object along with the children objects, 3635 * the reference object and the parent object recursively. 3636 * Apporiate SCN is triggered. 3637 * 3638 * lcp - the lookup control for the object being removed. 3639 * parent_flag - 1: the object being removed is the parent object; 3640 * 0: otherwise. 3641 * child_flag - 1: the object being removed is a child object; 3642 * 0: otherwise. 3643 * pending - 1: do not remove the ESI entry immediately; 3644 * 0: remove the ESI entry without any delay. 3645 * return - error code. 3646 * 3647 * **************************************************************************** 3648 */ 3649 static int 3650 do_dereg( 3651 lookup_ctrl_t *lcp, 3652 int parent_flag, 3653 int child_flag, 3654 int pending 3655 ) 3656 { 3657 int ec = 0; 3658 3659 isns_obj_t *obj; 3660 uint32_t *cuidp, num; 3661 isns_type_t type; 3662 uint32_t uid; 3663 int i; 3664 3665 /* remove the object from object container */ 3666 obj = cache_remove(lcp, 0); 3667 3668 if (obj == NULL) { 3669 return (0); 3670 } 3671 3672 /* trigger a scn */ 3673 if (scn_q != NULL) { 3674 (void) make_scn(ISNS_OBJECT_REMOVED, obj); 3675 } 3676 3677 /* dereg children */ 3678 i = 0; 3679 while (ec == 0 && !parent_flag && 3680 i < NUM_OF_CHILD[obj->type]) { 3681 type = TYPE_OF_CHILD[obj->type][i]; 3682 cuidp = get_child_n(obj, i); 3683 if (cuidp != NULL) { 3684 num = *cuidp; 3685 } else { 3686 num = 0; 3687 } 3688 while (ec == 0 && num > 0) { 3689 uid = cuidp[num]; 3690 if (uid != 0) { 3691 SET_UID_LCP(lcp, type, uid); 3692 ec = do_dereg(lcp, 3693 parent_flag, 3694 1, 3695 pending); 3696 } 3697 num --; 3698 } 3699 i ++; 3700 } 3701 3702 /* clear the ref bit on the ref'd object */ 3703 if (ec == 0 && TYPE_OF_REF[obj->type][0] > 0) { 3704 uid = 0; 3705 do { 3706 (void) setup_ref_lcp(lcp, obj, NULL); 3707 lcp->curr_uid = uid; 3708 lcp->data[2].ui = obj->type; 3709 if (cache_lookup(lcp, &uid, cb_clear_ref) != 0) { 3710 UPDATE_LCP_UID(lcp, uid); 3711 ec = do_dereg(lcp, 3712 parent_flag, 3713 child_flag, 3714 pending); 3715 } 3716 } while (uid != 0); 3717 } 3718 3719 /* remove it from the parent */ 3720 if (ec == 0 && !child_flag && 3721 TYPE_OF_PARENT[obj->type] > 0 && 3722 (uid = setup_parent_lcp(lcp, obj)) != 0) { 3723 if (cache_lookup(lcp, NULL, cb_remove_child) != 0) { 3724 UPDATE_LCP_UID(lcp, uid); 3725 ec = do_dereg(lcp, 3726 1, 3727 child_flag, 3728 0); 3729 } 3730 } 3731 3732 if (ec == 0 && !child_flag) { 3733 /* remove it from persistent data store */ 3734 if (sys_q) { 3735 ec = write_data(DATA_DELETE, obj); 3736 } 3737 /* remove esi event entry */ 3738 if (ec == 0) { 3739 (void) esi_remove_obj(obj, pending); 3740 } 3741 3742 /* save the parent uid for caller */ 3743 if (TYPE_OF_PARENT[obj->type] != 0) { 3744 lcp->curr_uid = get_parent_uid(obj); 3745 } else { 3746 /* it's the parent itself */ 3747 lcp->curr_uid = get_obj_uid(obj); 3748 } 3749 } 3750 3751 /* remove this portal from scn registry */ 3752 if (ec == 0 && 3753 obj->type == OBJ_PORTAL) { 3754 (void) remove_scn_portal(get_obj_uid(obj)); 3755 } 3756 3757 /* free the object */ 3758 (void) free_object(obj); 3759 3760 return (ec); 3761 } 3762 3763 /* 3764 * **************************************************************************** 3765 * 3766 * dereg_assoc: 3767 * Remove one association object from object container. 3768 * 3769 * lcp - the lookup control for the object being removed. 3770 * return - error code. 3771 * 3772 * **************************************************************************** 3773 */ 3774 int 3775 dereg_assoc( 3776 lookup_ctrl_t *lcp 3777 ) 3778 { 3779 isns_obj_t *obj; 3780 3781 obj = cache_remove(lcp, 1); 3782 3783 /* free the object */ 3784 if (obj != NULL) { 3785 free_object(obj); 3786 } 3787 3788 return (0); 3789 } 3790 3791 /* 3792 * **************************************************************************** 3793 * 3794 * dereg_object: 3795 * Remove one object from object container. 3796 * 3797 * lcp - the lookup control for the object being removed. 3798 * return - error code. 3799 * 3800 * **************************************************************************** 3801 */ 3802 int 3803 dereg_object( 3804 lookup_ctrl_t *lcp, 3805 int pending 3806 ) 3807 { 3808 return (do_dereg(lcp, 0, 0, pending)); 3809 } 3810 3811 /* 3812 * **************************************************************************** 3813 * 3814 * data_sync: 3815 * Synchronize the cache with persistent data store. 3816 * Flush the cache data to data store if the input ec is zero, 3817 * retreat the changes in cache and ignore data store update 3818 * if there is an error. 3819 * 3820 * ec - error code. 3821 * return - error code. 3822 * 3823 * **************************************************************************** 3824 */ 3825 int 3826 data_sync( 3827 int ec 3828 ) 3829 { 3830 /* cache is updated successfully, commit the data to data store */ 3831 if (IS_CACHE_UPDATED()) { 3832 if (ec == 0) { 3833 ec = write_data(DATA_COMMIT, NULL); 3834 } 3835 if (ec == 0) { 3836 /* successful, trigger the SCN */ 3837 (void) queue_msg_set(scn_q, SCN_TRIGGER, (void *)NULL); 3838 } else { 3839 shutdown_server(); 3840 } 3841 } else { 3842 /* ignore all SCNs which have been generated */ 3843 (void) queue_msg_set(scn_q, SCN_IGNORE, (void *)NULL); 3844 3845 (void) write_data(DATA_RETREAT, NULL); 3846 } 3847 3848 return (ec); 3849 } 3850 3851 static pthread_mutex_t name_mtx[3] = { 3852 PTHREAD_MUTEX_INITIALIZER, 3853 PTHREAD_MUTEX_INITIALIZER, 3854 PTHREAD_MUTEX_INITIALIZER 3855 }; 3856 static const char *name_pattern[3] = { 3857 "ENTITY_ID_%d", 3858 "DD_%d", 3859 "DD-Set_%d" 3860 }; 3861 static uint32_t name_count[3] = { 3862 0, 3863 0, 3864 0 3865 }; 3866 3867 /* 3868 * **************************************************************************** 3869 * 3870 * make_unique_name: 3871 * make a default unique name for a newly registered network entity, 3872 * discovery domain or discovery domain set object. 3873 * 3874 * len - pointer of the length of the new name for returning. 3875 * tag - which attribute of the new name is for. 3876 * return - the name being made. 3877 * 3878 * **************************************************************************** 3879 */ 3880 static char * 3881 make_unique_name( 3882 int *len, 3883 uint32_t tag 3884 ) 3885 { 3886 int i; 3887 int count; 3888 char name[32] = { 0 }; 3889 3890 char *p; 3891 3892 lookup_ctrl_t lc; 3893 3894 lc.curr_uid = 0; 3895 3896 switch (tag) { 3897 case ISNS_EID_ATTR_ID: 3898 i = 0; 3899 lc.type = OBJ_ENTITY; 3900 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID); 3901 break; 3902 case ISNS_DD_NAME_ATTR_ID: 3903 i = 1; 3904 lc.type = OBJ_DD; 3905 lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID); 3906 break; 3907 case ISNS_DD_SET_NAME_ATTR_ID: 3908 i = 2; 3909 lc.type = OBJ_DDS; 3910 lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID); 3911 break; 3912 default: 3913 ASSERT(0); 3914 break; 3915 } 3916 3917 lc.op[0] = OP_STRING; 3918 lc.op[1] = 0; 3919 do { 3920 (void) pthread_mutex_lock(&name_mtx[i]); 3921 count = ++ name_count[i]; 3922 (void) pthread_mutex_unlock(&name_mtx[i]); 3923 /* no more space, failure */ 3924 if (count == 0) { 3925 return (NULL); 3926 } 3927 (void) sprintf(name, name_pattern[i], count); 3928 lc.data[0].ptr = (uchar_t *)name; 3929 } while (is_obj_there(&lc) != 0); 3930 3931 /* 4-bytes aligned length */ 3932 *len = strlen(name); 3933 *len = *len + (4 - *len % 4); 3934 p = (char *)malloc(*len); 3935 if (p != NULL) { 3936 (void) strcpy(p, name); 3937 } 3938 return (p); 3939 } 3940 3941 #ifdef DEBUG 3942 void 3943 obj_dump( 3944 void *p 3945 ) 3946 { 3947 print_object(NULL, (isns_obj_t *)p); 3948 } 3949 #endif 3950