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