1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 34 #include "isns_server.h" 35 #include "isns_msgq.h" 36 #include "isns_func.h" 37 #include "isns_cache.h" 38 #include "isns_obj.h" 39 #include "isns_dd.h" 40 #include "isns_pdu.h" 41 #include "isns_qry.h" 42 #include "isns_scn.h" 43 #include "isns_utils.h" 44 #include "isns_cfg.h" 45 #include "isns_esi.h" 46 #include "isns_provider.h" 47 #include "isns_log.h" 48 49 /* 50 * extern global variables 51 */ 52 #ifdef DEBUG 53 extern int verbose_mc; 54 extern int verbose_tc; 55 #endif 56 extern const int NUM_OF_ATTRS[MAX_OBJ_TYPE_FOR_SIZE]; 57 extern const int NUM_OF_CHILD[MAX_OBJ_TYPE]; 58 extern const int TYPE_OF_PARENT[MAX_OBJ_TYPE_FOR_SIZE]; 59 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE]; 60 extern const int TAG_RANGE[MAX_OBJ_TYPE][3]; 61 62 /* scn message queue */ 63 extern msg_queue_t *scn_q; 64 65 /* 66 * extern functions. 67 */ 68 69 /* 70 * local variables 71 */ 72 73 /* 74 * local functions. 75 */ 76 static int dev_attr_reg(conn_arg_t *); 77 static int dev_attr_qry(conn_arg_t *); 78 static int dev_get_next(conn_arg_t *); 79 static int dev_dereg(conn_arg_t *); 80 static int scn_reg(conn_arg_t *); 81 static int scn_dereg(conn_arg_t *); 82 static int dd_reg(conn_arg_t *); 83 static int dd_dereg(conn_arg_t *); 84 static int dds_reg(conn_arg_t *); 85 static int dds_dereg(conn_arg_t *); 86 static int msg_error(conn_arg_t *); 87 88 /* 89 * **************************************************************************** 90 * 91 * packet_get_source: 92 * get the source attributes of the packet. 93 * 94 * conn - the argument of the connection. 95 * return - error code. 96 * 97 * **************************************************************************** 98 */ 99 static int 100 packet_get_source( 101 conn_arg_t *conn 102 ) 103 { 104 int ec = 0; 105 106 isns_pdu_t *pdu = conn->in_packet.pdu; 107 isns_tlv_t *source = pdu_get_source(pdu); 108 109 if (source == NULL) { 110 ec = ISNS_RSP_SRC_ABSENT; 111 } else if (source->attr_id != ISNS_ISCSI_NAME_ATTR_ID || 112 source->attr_len == 0) { 113 ec = ISNS_RSP_SRC_UNKNOWN; 114 } 115 116 if (ec == 0) { 117 conn->in_packet.source = source; 118 } 119 120 return (ec); 121 } 122 123 /* 124 * **************************************************************************** 125 * 126 * packet_get_key: 127 * get the key attributes of the packet. 128 * 129 * conn - the argument of the connection. 130 * return - error code. 131 * 132 * **************************************************************************** 133 */ 134 static int 135 packet_get_key( 136 conn_arg_t *conn 137 ) 138 { 139 int ec = 0; 140 141 isns_pdu_t *pdu = conn->in_packet.pdu; 142 isns_tlv_t *key; 143 size_t key_len; 144 145 key = pdu_get_key(pdu, &key_len); 146 147 conn->in_packet.key = key; 148 conn->in_packet.key_len = key_len; 149 150 return (ec); 151 } 152 153 /* 154 * **************************************************************************** 155 * 156 * packet_get_operand: 157 * get the operating attributes of the packet. 158 * 159 * conn - the argument of the connection. 160 * return - error code. 161 * 162 * **************************************************************************** 163 */ 164 static int 165 packet_get_operand( 166 conn_arg_t *conn 167 ) 168 { 169 int ec = 0; 170 171 isns_pdu_t *pdu = conn->in_packet.pdu; 172 isns_tlv_t *op; 173 size_t op_len; 174 175 op = pdu_get_operand(pdu, &op_len); 176 177 conn->in_packet.op = op; 178 conn->in_packet.op_len = op_len; 179 180 return (ec); 181 } 182 183 /* 184 * **************************************************************************** 185 * 186 * packet_split_verify: 187 * split and verify the packet, get the apporiate locking type and 188 * function handler for the packet. 189 * 190 * conn - the argument of the connection. 191 * return - error code. 192 * 193 * **************************************************************************** 194 */ 195 int 196 packet_split_verify( 197 conn_arg_t *conn 198 ) 199 { 200 int ec = 0; 201 202 isns_pdu_t *pdu = conn->in_packet.pdu; 203 204 int (*handler)(conn_arg_t *) = msg_error; 205 int lock = CACHE_NO_ACTION; 206 207 if (pdu->version != ISNSP_VERSION) { 208 ec = ISNS_RSP_VER_NOT_SUPPORTED; 209 } else { 210 switch (pdu->func_id) { 211 case ISNS_DEV_ATTR_REG: 212 lock = CACHE_WRITE; 213 handler = dev_attr_reg; 214 break; 215 case ISNS_DEV_ATTR_QRY: 216 lock = CACHE_READ; 217 handler = dev_attr_qry; 218 break; 219 case ISNS_DEV_GET_NEXT: 220 lock = CACHE_READ; 221 handler = dev_get_next; 222 break; 223 case ISNS_DEV_DEREG: 224 lock = CACHE_WRITE; 225 handler = dev_dereg; 226 break; 227 case ISNS_SCN_REG: 228 if (scn_q != NULL) { 229 lock = CACHE_WRITE; 230 handler = scn_reg; 231 } else { 232 ec = ISNS_RSP_SCN_REGIS_REJECTED; 233 } 234 break; 235 case ISNS_SCN_DEREG: 236 if (scn_q != NULL) { 237 lock = CACHE_WRITE; 238 handler = scn_dereg; 239 } else { 240 ec = ISNS_RSP_SCN_REGIS_REJECTED; 241 } 242 break; 243 case ISNS_SCN_EVENT: 244 ec = ISNS_RSP_MSG_NOT_SUPPORTED; 245 break; 246 case ISNS_DD_REG: 247 lock = CACHE_WRITE; 248 handler = dd_reg; 249 break; 250 case ISNS_DD_DEREG: 251 lock = CACHE_WRITE; 252 handler = dd_dereg; 253 break; 254 case ISNS_DDS_REG: 255 lock = CACHE_WRITE; 256 handler = dds_reg; 257 break; 258 case ISNS_DDS_DEREG: 259 lock = CACHE_WRITE; 260 handler = dds_dereg; 261 break; 262 default: 263 ec = ISNS_RSP_MSG_NOT_SUPPORTED; 264 break; 265 } 266 } 267 268 if (ISNS_OPERATION_TYPE_ENABLED()) { 269 char buf[INET6_ADDRSTRLEN]; 270 struct sockaddr_storage *ssp = &conn->ss; 271 struct sockaddr_in *sinp = (struct sockaddr_in *)ssp; 272 if (ssp->ss_family == AF_INET) { 273 (void) inet_ntop(AF_INET, (void *)&(sinp->sin_addr), 274 buf, sizeof (buf)); 275 } else { 276 (void) inet_ntop(AF_INET6, (void *)&(sinp->sin_addr), 277 buf, sizeof (buf)); 278 } 279 ISNS_OPERATION_TYPE((uintptr_t)buf, pdu->func_id); 280 } 281 282 conn->lock = lock; 283 conn->handler = handler; 284 285 /* packet split & verify */ 286 if (ec == 0) { 287 ec = packet_get_source(conn); 288 if (ec == 0) { 289 ec = packet_get_key(conn); 290 if (ec == 0) { 291 ec = packet_get_operand(conn); 292 } 293 } 294 } 295 296 conn->ec = ec; 297 298 return (ec); 299 } 300 301 /* 302 * **************************************************************************** 303 * 304 * setup_key_lcp: 305 * setup the lookup control data for looking up the object 306 * which the key attributes identify. 307 * 308 * lcp - the pointer of the lookup control data. 309 * key - the key attributes. 310 * key_len - the length of the key attributes. 311 * return - the pointer of the lookup control data or 312 * NULL if there is an error. 313 * 314 * **************************************************************************** 315 */ 316 static int 317 setup_key_lcp( 318 lookup_ctrl_t *lcp, 319 isns_tlv_t *key, 320 uint16_t key_len 321 ) 322 { 323 int ec = 0; 324 325 uint8_t *value = &key->attr_value[0]; 326 327 lcp->curr_uid = 0; 328 lcp->op[0] = 0; 329 330 switch (key->attr_id) { 331 case ISNS_EID_ATTR_ID: 332 if (key->attr_len >= 4) { 333 lcp->type = OBJ_ENTITY; 334 lcp->id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID); 335 lcp->op[0] = OP_STRING; 336 lcp->data[0].ptr = (uchar_t *)value; 337 lcp->op[1] = 0; 338 } 339 break; 340 case ISNS_ISCSI_NAME_ATTR_ID: 341 if (key->attr_len >= 4) { 342 lcp->type = OBJ_ISCSI; 343 lcp->id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 344 lcp->op[0] = OP_STRING; 345 lcp->data[0].ptr = (uchar_t *)value; 346 lcp->op[1] = 0; 347 } else { 348 ec = ISNS_RSP_MSG_FORMAT_ERROR; 349 } 350 break; 351 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 352 if (key->attr_len == sizeof (in6_addr_t)) { 353 lcp->id[0] = ATTR_INDEX_PORTAL( 354 ISNS_PORTAL_IP_ADDR_ATTR_ID); 355 lcp->op[0] = OP_MEMORY_IP6; 356 lcp->data[0].ip = (in6_addr_t *)value; 357 NEXT_TLV(key, key_len); 358 if (key_len <= 8 || 359 key->attr_len != 4 || 360 key->attr_id != ISNS_PORTAL_PORT_ATTR_ID) { 361 return (ISNS_RSP_MSG_FORMAT_ERROR); 362 } 363 lcp->type = OBJ_PORTAL; 364 value = &key->attr_value[0]; 365 lcp->id[1] = ATTR_INDEX_PORTAL( 366 ISNS_PORTAL_PORT_ATTR_ID); 367 lcp->op[1] = OP_INTEGER; 368 lcp->data[1].ui = ntohl(*(uint32_t *)value); 369 lcp->op[2] = 0; 370 } else { 371 ec = ISNS_RSP_MSG_FORMAT_ERROR; 372 } 373 break; 374 case ISNS_PG_ISCSI_NAME_ATTR_ID: 375 if (key->attr_len < 4) { 376 return (ISNS_RSP_MSG_FORMAT_ERROR); 377 } 378 lcp->id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID); 379 lcp->op[0] = OP_STRING; 380 lcp->data[0].ptr = (uchar_t *)value; 381 NEXT_TLV(key, key_len); 382 if (key_len <= 8 || 383 key->attr_len != sizeof (in6_addr_t) || 384 key->attr_id != ISNS_PG_PORTAL_IP_ADDR_ATTR_ID) { 385 return (ISNS_RSP_MSG_FORMAT_ERROR); 386 } 387 value = &key->attr_value[0]; 388 lcp->id[1] = ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID); 389 lcp->op[1] = OP_MEMORY_IP6; 390 lcp->data[1].ip = (in6_addr_t *)value; 391 NEXT_TLV(key, key_len); 392 if (key_len <= 8 || 393 key->attr_len != 4 || 394 key->attr_id != ISNS_PG_PORTAL_PORT_ATTR_ID) { 395 return (ISNS_RSP_MSG_FORMAT_ERROR); 396 } 397 value = &key->attr_value[0]; 398 lcp->id[2] = ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID); 399 lcp->op[2] = OP_INTEGER; 400 lcp->data[2].ui = ntohl(*(uint32_t *)value); 401 lcp->type = OBJ_PG; 402 break; 403 default: 404 lcp->type = 0; /* invalid */ 405 ec = ISNS_RSP_MSG_FORMAT_ERROR; 406 } 407 408 return (ec); 409 } 410 411 /* 412 * **************************************************************************** 413 * 414 * rsp_add_op: 415 * add the operating attributes to the response packet. 416 * 417 * conn - the argument of the connection. 418 * obj - the object which is being added as operating attributes. 419 * return - error code. 420 * 421 * **************************************************************************** 422 */ 423 static int 424 rsp_add_op( 425 conn_arg_t *conn, 426 isns_obj_t *obj 427 ) 428 { 429 int ec = 0; 430 431 isns_attr_t *attr; 432 int i; 433 434 isns_pdu_t *rsp = conn->out_packet.pdu; 435 size_t pl = conn->out_packet.pl; 436 size_t sz = conn->out_packet.sz; 437 438 i = 0; 439 while (i < NUM_OF_ATTRS[obj->type] && 440 ec == 0) { 441 attr = &obj->attrs[i]; 442 /* there is an attribute, send it back */ 443 if (attr->tag != 0) { 444 ec = pdu_add_tlv(&rsp, &pl, &sz, 445 attr->tag, attr->len, 446 (void *)attr->value.ptr, 0); 447 } 448 i ++; 449 } 450 451 conn->out_packet.pdu = rsp; 452 conn->out_packet.pl = pl; 453 conn->out_packet.sz = sz; 454 455 return (ec); 456 } 457 458 /* 459 * **************************************************************************** 460 * 461 * rsp_add_key: 462 * add the key attributes to the response packet. 463 * 464 * conn - the argument of the connection. 465 * entity - the object which is being added as key attributes. 466 * return - error code. 467 * 468 * **************************************************************************** 469 */ 470 static int 471 rsp_add_key( 472 conn_arg_t *conn, 473 isns_obj_t *entity 474 ) 475 { 476 int ec = 0; 477 478 isns_tlv_t *key = conn->in_packet.key; 479 size_t key_len = conn->in_packet.key_len; 480 uint32_t tag = ISNS_EID_ATTR_ID; 481 isns_attr_t *attr = &entity->attrs[ATTR_INDEX_ENTITY(tag)]; 482 uint32_t len = attr->len; 483 484 isns_pdu_t *rsp = conn->out_packet.pdu; 485 size_t pl = conn->out_packet.pl; 486 size_t sz = conn->out_packet.sz; 487 488 if (key_len == 0) { 489 ec = pdu_add_tlv(&rsp, &pl, &sz, 490 tag, len, (void *)attr->value.ptr, 0); 491 } else { 492 while (key_len >= 8 && 493 ec == 0) { 494 if (key->attr_id == ISNS_EID_ATTR_ID) { 495 ec = pdu_add_tlv(&rsp, &pl, &sz, 496 tag, len, 497 (void *)attr->value.ptr, 0); 498 } else { 499 ec = pdu_add_tlv(&rsp, &pl, &sz, 500 key->attr_id, key->attr_len, 501 (void *)key->attr_value, 1); 502 } 503 NEXT_TLV(key, key_len); 504 } 505 } 506 507 if (ec == 0) { 508 ec = pdu_add_tlv(&rsp, &pl, &sz, 509 ISNS_DELIMITER_ATTR_ID, 0, NULL, 0); 510 } 511 512 conn->out_packet.pdu = rsp; 513 conn->out_packet.pl = pl; 514 conn->out_packet.sz = sz; 515 516 if (ec == 0) { 517 ec = rsp_add_op(conn, entity); 518 } 519 520 return (ec); 521 } 522 523 /* 524 * **************************************************************************** 525 * 526 * rsp_add_tlv: 527 * add one attribute with TLV format to the response packet. 528 * 529 * conn - the argument of the connection. 530 * tag - the tag of the attribute. 531 * len - the length of the attribute. 532 * value- the value of the attribute. 533 * pflag- the flag of the value, 0: value; 1: pointer to value 534 * return - error code. 535 * 536 * **************************************************************************** 537 */ 538 static int 539 rsp_add_tlv( 540 conn_arg_t *conn, 541 uint32_t tag, 542 uint32_t len, 543 void *value, 544 int pflag 545 ) 546 { 547 int ec = 0; 548 549 isns_pdu_t *rsp = conn->out_packet.pdu; 550 size_t pl = conn->out_packet.pl; 551 size_t sz = conn->out_packet.sz; 552 553 ec = pdu_add_tlv(&rsp, &pl, &sz, tag, len, value, pflag); 554 555 conn->out_packet.pdu = rsp; 556 conn->out_packet.pl = pl; 557 conn->out_packet.sz = sz; 558 559 return (ec); 560 } 561 562 /* 563 * **************************************************************************** 564 * 565 * rsp_add_tlvs: 566 * add attributes with TLV format to the response packet. 567 * 568 * conn - the argument of the connection. 569 * tlv - the attributes with TLV format being added. 570 * tlv_len - the length of the attributes. 571 * return - error code. 572 * 573 * **************************************************************************** 574 */ 575 static int 576 rsp_add_tlvs( 577 conn_arg_t *conn, 578 isns_tlv_t *tlv, 579 uint32_t tlv_len 580 ) 581 { 582 int ec = 0; 583 584 uint32_t tag; 585 uint32_t len; 586 void *value; 587 588 while (tlv_len >= 8 && 589 ec == 0) { 590 tag = tlv->attr_id; 591 len = tlv->attr_len; 592 value = (void *)tlv->attr_value; 593 594 ec = rsp_add_tlv(conn, tag, len, value, 1); 595 596 NEXT_TLV(tlv, tlv_len); 597 } 598 599 return (ec); 600 } 601 602 /* 603 * **************************************************************************** 604 * 605 * dev_attr_reg: 606 * function which handles the isnsp DEV_ATTR_REG message. 607 * 608 * conn - the argument of the connection. 609 * return - 0: the message requires response. 610 * 611 * **************************************************************************** 612 */ 613 static int 614 dev_attr_reg( 615 conn_arg_t *conn 616 ) 617 { 618 int ec = 0; 619 620 isns_pdu_t *pdu = conn->in_packet.pdu; 621 isns_tlv_t *source = conn->in_packet.source; 622 isns_tlv_t *key = conn->in_packet.key; 623 uint16_t key_len = conn->in_packet.key_len; 624 isns_tlv_t *op = conn->in_packet.op; 625 uint16_t op_len = conn->in_packet.op_len; 626 627 boolean_t replace = 628 ((pdu->flags & ISNS_FLAG_REPLACE_REG) == ISNS_FLAG_REPLACE_REG); 629 630 lookup_ctrl_t lc, lc_key; 631 uchar_t *iscsi_name; 632 int ctrl; 633 634 isns_obj_t *ety = NULL; /* network entity object */ 635 isns_type_t ptype; /* parent object type */ 636 uint32_t puid; /* parent object UID */ 637 void const **child[MAX_CHILD_TYPE] = { NULL }; /* children */ 638 int ety_update, obj_update; 639 isns_attr_t *eid_attr; 640 641 isns_obj_t *obj; /* child object */ 642 isns_type_t ctype; /* child object type */ 643 uint32_t uid; /* child object uid */ 644 isns_attr_t pgt[3] = { NULL }; 645 646 void const **vpp = NULL; 647 int i = 0; 648 649 isnslog(LOG_DEBUG, "dev_attr_reg", "entered (replace: %d)", replace); 650 651 ec = pdu_reset_rsp(&conn->out_packet.pdu, 652 &conn->out_packet.pl, 653 &conn->out_packet.sz); 654 if (ec != 0) { 655 goto reg_done; 656 } 657 658 iscsi_name = (uchar_t *)&source->attr_value[0]; 659 ctrl = is_control_node(iscsi_name); 660 lc_key.type = 0; 661 if (key != NULL) { 662 /* validate key attributes and make lcp for */ 663 /* the object identified by key attributes. */ 664 ec = setup_key_lcp(&lc, key, key_len); 665 if (ec == 0 && lc.type != 0) { 666 lc_key = lc; 667 /* object is not found */ 668 if ((uid = is_obj_there(&lc)) == 0) { 669 /* error if it is a network entity */ 670 if (lc.type != OBJ_ENTITY) { 671 ec = ISNS_RSP_INVALID_REGIS; 672 } 673 /* validate for the source attribute before */ 674 /* update or replace the network entity object */ 675 } else if (ctrl == 0 && 676 #ifndef SKIP_SRC_AUTH 677 reg_auth_src(lc.type, uid, iscsi_name) == 0) { 678 #else 679 0) { 680 #endif 681 ec = ISNS_RSP_SRC_UNAUTHORIZED; 682 /* de-register the network entity if replace is true */ 683 } else if (replace != 0) { 684 UPDATE_LCP_UID(&lc, uid); 685 ec = dereg_object(&lc, 0); 686 /* generate a SCN */ 687 if (ec == 0) { 688 (void) queue_msg_set(scn_q, 689 SCN_TRIGGER, NULL); 690 } 691 } 692 } 693 } 694 if (ec != 0) { 695 goto reg_done; 696 } 697 698 /* register the network entity object */ 699 ec = reg_get_entity(&ety, &op, &op_len); 700 if (ec != 0) { 701 goto reg_done; 702 } 703 if (ety == NULL && lc_key.type != OBJ_ENTITY) { 704 ety = make_default_entity(); 705 } else if (ety == NULL || 706 (lc_key.type == OBJ_ENTITY && 707 key_cmp(&lc_key, ety) != 0)) { 708 /* the eid in key attribute and */ 709 /* op attribute must be the same */ 710 ec = ISNS_RSP_INVALID_REGIS; 711 goto reg_done; 712 } 713 if (ety == NULL || rsp_add_key(conn, ety) != 0) { 714 ec = ISNS_RSP_INTERNAL_ERROR; 715 } else { 716 eid_attr = &ety->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)]; 717 ec = register_object(ety, &puid, &ety_update); 718 ptype = OBJ_ENTITY; 719 } 720 if (ec == 0 && ety_update == 0) { 721 /* newly registered, reset the pointer */ 722 ety = NULL; 723 } 724 725 /* register the reset of objects which are specified in */ 726 /* operating attributes */ 727 while (ec == 0 && 728 (ec = reg_get_obj(&obj, &pgt[0], &op, &op_len)) == 0 && 729 obj != NULL && 730 (ec = rsp_add_op(conn, obj)) == 0) { 731 ctype = obj->type; 732 /* set the parent object UID */ 733 (void) set_parent_obj(obj, puid); 734 /* register it */ 735 ec = register_object(obj, &uid, &obj_update); 736 if (ec == 0) { 737 if (obj_update == 0 || 738 is_obj_online(obj) == 0) { 739 /* update the ref'd object */ 740 (void) update_ref_obj(obj); 741 /* add the newly registered object info */ 742 /* to child info array of the parent object */ 743 ec = buff_child_obj(ptype, ctype, obj, child); 744 } else { 745 if (ctrl == 0 && 746 #ifndef SKIP_SRC_AUTH 747 puid != get_parent_uid(obj)) { 748 #else 749 0) { 750 #endif 751 ec = ISNS_RSP_SRC_UNAUTHORIZED; 752 } 753 /* it was for updating an existing object */ 754 free_one_object(obj); 755 } 756 } else { 757 /* failed registering it */ 758 free_one_object(obj); 759 } 760 } 761 762 /* update the portal group object for the associations between */ 763 /* the newly registered objects and previously registered objects */ 764 if (ec == 0) { 765 ec = verify_ref_obj(ptype, puid, child); 766 } 767 if (ec != 0) { 768 goto reg_done; 769 } 770 771 /* update the children list of the parent object */ 772 while (i < MAX_CHILD_TYPE) { 773 vpp = child[i]; 774 if (vpp != NULL) { 775 break; 776 } 777 i ++; 778 } 779 if (vpp != NULL) { 780 ec = update_child_obj(ptype, puid, child, 1); 781 } else { 782 #ifndef SKIP_SRC_AUTH 783 ec = ISNS_RSP_INVALID_REGIS; 784 #else 785 /* for interop-ability, we cannot treat this as */ 786 /* an error, instead, remove the network entity */ 787 SET_UID_LCP(&lc, OBJ_ENTITY, puid); 788 ec = dereg_object(&lc, 0); 789 goto reg_done; 790 #endif 791 } 792 if (ec != 0) { 793 goto reg_done; 794 } 795 /* add esi entry */ 796 if (ety_update != 0) { 797 (void) esi_remove(puid); 798 } 799 ec = esi_add(puid, eid_attr->value.ptr, eid_attr->len); 800 801 reg_done: 802 conn->ec = ec; 803 free_one_object(ety); 804 uid = 0; 805 while (uid < MAX_CHILD_TYPE) { 806 if (child[uid] != NULL) { 807 free(child[uid]); 808 } 809 uid ++; 810 } 811 812 if (ec != 0) { 813 isnslog(LOG_DEBUG, "dev_attr_reg", "error code: %d", ec); 814 } 815 816 return (0); 817 } 818 819 /* 820 * **************************************************************************** 821 * 822 * dev_attr_qry: 823 * function which handles the isnsp DEV_ATTR_QRY message. 824 * 825 * conn - the argument of the connection. 826 * return - 0: the message requires response. 827 * 828 * **************************************************************************** 829 */ 830 static int 831 dev_attr_qry( 832 conn_arg_t *conn 833 ) 834 { 835 int ec = 0; 836 837 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 838 isns_tlv_t *source = conn->in_packet.source; 839 isns_tlv_t *key = conn->in_packet.key; 840 uint16_t key_len = conn->in_packet.key_len; 841 isns_tlv_t *op = conn->in_packet.op; 842 uint16_t op_len = conn->in_packet.op_len; 843 844 uchar_t *iscsi_name; 845 846 bmp_t *nodes_bmp = NULL; 847 uint32_t num_of_nodes; 848 uint32_t *key_uids = NULL; 849 uint32_t num_of_keys; 850 isns_type_t key_type; 851 852 uint32_t key_uid; 853 uint32_t op_uid; 854 855 uint32_t size_of_ops; 856 uint32_t num_of_ops; 857 uint32_t *op_uids = NULL; 858 isns_type_t op_type; 859 860 isns_tlv_t *tlv; 861 uint16_t tlv_len; 862 863 isnslog(LOG_DEBUG, "dev_attr_qry", "entered"); 864 865 ec = pdu_reset_rsp(&conn->out_packet.pdu, 866 &conn->out_packet.pl, 867 &conn->out_packet.sz); 868 if (ec != 0) { 869 goto qry_done; 870 } 871 872 /* 873 * RFC 4171 section 5.7.5.2: 874 * If no Operating Attributes are included in the original query, then 875 * all Operating Attributes SHALL be returned in the response. ??? 876 */ 877 if (op_len == 0) { 878 goto qry_done; 879 } 880 881 iscsi_name = (uchar_t *)&source->attr_value[0]; 882 if (is_control_node(iscsi_name) == 0) { 883 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes); 884 if (ec != 0 || nodes_bmp == NULL) { 885 goto qry_done; 886 } 887 } 888 889 size_of_ops = 0; 890 if (key != NULL) { 891 /* 892 * Return the original message key. 893 */ 894 ec = rsp_add_tlvs(conn, key, key_len); 895 if (ec != 0) { 896 goto qry_done; 897 } 898 899 /* 900 * Delimiter 901 */ 902 ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0); 903 if (ec != 0) { 904 goto qry_done; 905 } 906 907 /* 908 * Query objects which match the Key Attributes. 909 */ 910 ec = get_qry_keys(nodes_bmp, num_of_nodes, &key_type, 911 key, key_len, &key_uids, &num_of_keys); 912 if (ec != 0 || key_uids == NULL) { 913 goto qry_done; 914 } 915 916 /* 917 * Iterate thru each object identified by the message key. 918 */ 919 tlv = op; 920 tlv_len = op_len; 921 FOR_EACH_OBJS(key_uids, num_of_keys, key_uid, { 922 /* 923 * Iterate thru each Operating Attributes. 924 */ 925 op = tlv; 926 op_len = tlv_len; 927 FOR_EACH_OP(op, op_len, op_type, { 928 if (op_type == 0) { 929 ec = ISNS_RSP_INVALID_QRY; 930 goto qry_done; 931 } 932 ec = get_qry_ops(key_uid, key_type, 933 op_type, &op_uids, 934 &num_of_ops, &size_of_ops); 935 if (ec != 0) { 936 goto qry_done; 937 } 938 /* 939 * Iterate thru each object for the Operating 940 * Attributes again. 941 */ 942 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, { 943 ec = get_qry_attrs(op_uid, op_type, 944 op, op_len, conn); 945 if (ec != 0) { 946 goto qry_done; 947 } 948 }); 949 }); 950 }); 951 } else { 952 /* 953 * Iterate thru each Operating Attributes. 954 */ 955 FOR_EACH_OP(op, op_len, op_type, { 956 ec = get_qry_ops2(nodes_bmp, num_of_nodes, 957 op_type, &op_uids, 958 &num_of_ops, &size_of_ops); 959 if (ec != 0) { 960 goto qry_done; 961 } 962 /* 963 * Iterate thru each object for the Operating 964 * Attributes again. 965 */ 966 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, { 967 ec = get_qry_attrs(op_uid, op_type, 968 op, op_len, conn); 969 if (ec != 0) { 970 goto qry_done; 971 } 972 }); 973 }); 974 } 975 976 qry_done: 977 conn->ec = ec; 978 979 if (ec != 0) { 980 isnslog(LOG_DEBUG, "dev_attr_qry", "error code: %d", ec); 981 } 982 983 free(nodes_bmp); 984 free(key_uids); 985 free(op_uids); 986 987 return (0); 988 } 989 990 /* 991 * **************************************************************************** 992 * 993 * dev_get_next: 994 * function which handles the isnsp DEV_GET_NEXT message. 995 * 996 * conn - the argument of the connection. 997 * return - 0: the message requires response. 998 * 999 * **************************************************************************** 1000 */ 1001 static int 1002 dev_get_next( 1003 conn_arg_t *conn 1004 ) 1005 { 1006 int ec = 0; 1007 1008 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1009 isns_tlv_t *source = conn->in_packet.source; 1010 isns_tlv_t *key = conn->in_packet.key; 1011 uint16_t key_len = conn->in_packet.key_len; 1012 isns_tlv_t *op = conn->in_packet.op; 1013 uint16_t op_len = conn->in_packet.op_len; 1014 1015 uchar_t *iscsi_name; 1016 1017 bmp_t *nodes_bmp = NULL; 1018 uint32_t num_of_nodes; 1019 1020 isns_type_t key_type; 1021 isns_type_t op_type; 1022 uint32_t size_of_obj; 1023 uint32_t num_of_obj; 1024 uint32_t *obj_uids = NULL; 1025 1026 uint32_t uid; 1027 1028 isnslog(LOG_DEBUG, "dev_get_next", "entered"); 1029 1030 ec = pdu_reset_rsp(&conn->out_packet.pdu, 1031 &conn->out_packet.pl, 1032 &conn->out_packet.sz); 1033 if (ec != 0) { 1034 goto get_next_done; 1035 } 1036 1037 iscsi_name = (uchar_t *)&source->attr_value[0]; 1038 if (is_control_node(iscsi_name) == 0) { 1039 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes); 1040 if (nodes_bmp == NULL) { 1041 ec = ISNS_RSP_NO_SUCH_ENTRY; 1042 } 1043 if (ec != 0) { 1044 goto get_next_done; 1045 } 1046 } 1047 1048 /* 1049 * Get Message Key type and validate the Message Key. 1050 */ 1051 key_type = TLV2TYPE(key); 1052 if (key_type == 0) { 1053 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1054 goto get_next_done; 1055 } 1056 ec = validate_qry_key(key_type, key, key_len, NULL); 1057 if (ec != 0) { 1058 goto get_next_done; 1059 } 1060 1061 size_of_obj = 0; 1062 if (op != NULL) { 1063 /* 1064 * Query the objects which match the Operating Attributes. 1065 */ 1066 ec = get_qry_keys(nodes_bmp, num_of_nodes, &op_type, 1067 op, op_len, &obj_uids, &num_of_obj); 1068 if (op_type != key_type) { 1069 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1070 } 1071 } else { 1072 /* 1073 * Query the objects which match the Message Key type. 1074 */ 1075 ec = get_qry_ops2(nodes_bmp, num_of_nodes, 1076 key_type, &obj_uids, &num_of_obj, &size_of_obj); 1077 } 1078 if (ec != 0) { 1079 goto get_next_done; 1080 } 1081 1082 /* 1083 * Get the object which is next to the one indicated by the 1084 * Message Key. 1085 */ 1086 uid = get_next_obj(key, key_len, key_type, obj_uids, num_of_obj); 1087 if (uid == 0) { 1088 ec = ISNS_RSP_NO_SUCH_ENTRY; 1089 goto get_next_done; 1090 } 1091 1092 /* 1093 * Message Key 1094 */ 1095 if ((ec = get_qry_attrs1(uid, key_type, key, key_len, conn)) != 0) { 1096 goto get_next_done; 1097 } 1098 1099 /* 1100 * Delimiter 1101 */ 1102 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)) != 0) { 1103 goto get_next_done; 1104 } 1105 1106 /* 1107 * Operating Attributes 1108 */ 1109 if (op != NULL) { 1110 ec = get_qry_attrs(uid, op_type, op, op_len, conn); 1111 } 1112 1113 get_next_done: 1114 conn->ec = ec; 1115 1116 if (ec != 0 && ec != ISNS_RSP_NO_SUCH_ENTRY) { 1117 isnslog(LOG_DEBUG, "dev_get_next", "error code: %d", ec); 1118 } 1119 1120 free(nodes_bmp); 1121 free(obj_uids); 1122 1123 return (0); 1124 } 1125 1126 /* 1127 * **************************************************************************** 1128 * 1129 * dev_dereg: 1130 * function which handles the isnsp DEV_DEREG message. 1131 * 1132 * conn - the argument of the connection. 1133 * return - 0: the message requires response. 1134 * 1135 * **************************************************************************** 1136 */ 1137 static int 1138 dev_dereg( 1139 conn_arg_t *conn 1140 ) 1141 { 1142 int ec = 0; 1143 1144 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1145 isns_tlv_t *source = conn->in_packet.source; 1146 /* isns_tlv_t *key = conn->in_packet.key; */ 1147 /* uint16_t key_len = conn->in_packet.key_len; */ 1148 isns_tlv_t *op = conn->in_packet.op; 1149 uint16_t op_len = conn->in_packet.op_len; 1150 1151 uchar_t *iscsi_name; 1152 int ctrl; 1153 uint32_t puid; 1154 1155 lookup_ctrl_t lc; 1156 uint8_t *value; 1157 1158 isnslog(LOG_DEBUG, "dev_dereg", "entered"); 1159 1160 iscsi_name = (uchar_t *)&source->attr_value[0]; 1161 ctrl = is_control_node(iscsi_name); 1162 if (ctrl == 0) { 1163 puid = is_parent_there(iscsi_name); 1164 } 1165 1166 while (op_len > 8 && ec == 0) { 1167 lc.curr_uid = 0; 1168 value = &op->attr_value[0]; 1169 switch (op->attr_id) { 1170 case ISNS_EID_ATTR_ID: 1171 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID); 1172 lc.op[0] = OP_STRING; 1173 lc.data[0].ptr = (uchar_t *)value; 1174 lc.op[1] = 0; 1175 lc.type = OBJ_ENTITY; 1176 break; 1177 case ISNS_ISCSI_NAME_ATTR_ID: 1178 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 1179 lc.op[0] = OP_STRING; 1180 lc.data[0].ptr = (uchar_t *)value; 1181 lc.op[1] = 0; 1182 lc.type = OBJ_ISCSI; 1183 break; 1184 case ISNS_ISCSI_NODE_INDEX_ATTR_ID: 1185 lc.id[0] = ATTR_INDEX_ISCSI( 1186 ISNS_ISCSI_NODE_INDEX_ATTR_ID); 1187 lc.op[0] = OP_INTEGER; 1188 lc.data[0].ui = ntohl(*(uint32_t *)value); 1189 lc.op[1] = 0; 1190 lc.type = OBJ_ISCSI; 1191 break; 1192 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 1193 lc.id[0] = ATTR_INDEX_PORTAL( 1194 ISNS_PORTAL_IP_ADDR_ATTR_ID); 1195 lc.op[0] = OP_MEMORY_IP6; 1196 lc.data[0].ip = (in6_addr_t *)value; 1197 NEXT_TLV(op, op_len); 1198 if (op_len > 8 && 1199 op->attr_id == ISNS_PORTAL_PORT_ATTR_ID) { 1200 value = &op->attr_value[0]; 1201 lc.id[1] = ATTR_INDEX_PORTAL( 1202 ISNS_PORTAL_PORT_ATTR_ID); 1203 lc.op[1] = OP_INTEGER; 1204 lc.data[1].ui = ntohl(*(uint32_t *)value); 1205 lc.op[2] = 0; 1206 lc.type = OBJ_PORTAL; 1207 } else { 1208 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1209 } 1210 break; 1211 case ISNS_PORTAL_INDEX_ATTR_ID: 1212 lc.id[0] = ATTR_INDEX_PORTAL( 1213 ISNS_PORTAL_INDEX_ATTR_ID); 1214 lc.op[0] = OP_INTEGER; 1215 lc.data[0].ui = ntohl(*(uint32_t *)value); 1216 lc.op[1] = 0; 1217 lc.type = OBJ_PORTAL; 1218 break; 1219 default: 1220 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1221 break; 1222 } 1223 if (ec == 0 && 1224 (ec = dereg_object(&lc, 0)) == 0) { 1225 if (ctrl == 0 && 1226 #ifndef SKIP_SRC_AUTH 1227 lc.curr_uid != 0 && 1228 puid != lc.curr_uid) { 1229 #else 1230 0) { 1231 #endif 1232 ec = ISNS_RSP_SRC_UNAUTHORIZED; 1233 } else { 1234 NEXT_TLV(op, op_len); 1235 } 1236 } 1237 } 1238 1239 conn->ec = ec; 1240 1241 if (ec != 0) { 1242 isnslog(LOG_DEBUG, "dev_dereg", "error code: %d", ec); 1243 } 1244 1245 return (0); 1246 } 1247 1248 /* 1249 * **************************************************************************** 1250 * 1251 * scn_reg: 1252 * function which handles the isnsp SCN_REG message. 1253 * 1254 * conn - the argument of the connection. 1255 * return - 0: the message requires response. 1256 * 1257 * **************************************************************************** 1258 */ 1259 static int 1260 scn_reg( 1261 conn_arg_t *conn 1262 ) 1263 { 1264 int ec = 0; 1265 1266 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1267 /* isns_tlv_t *source = conn->in_packet.source; */ 1268 isns_tlv_t *key = conn->in_packet.key; 1269 uint16_t key_len = conn->in_packet.key_len; 1270 isns_tlv_t *op = conn->in_packet.op; 1271 uint16_t op_len = conn->in_packet.op_len; 1272 1273 /* uchar_t *src; */ 1274 uchar_t *node_name; 1275 uint32_t nlen; 1276 uint32_t scn; 1277 1278 isnslog(LOG_DEBUG, "scn_reg", "entered"); 1279 1280 /* src = (uchar_t *)&source->attr_value[0]; */ 1281 1282 if (op == NULL || 1283 op->attr_id != ISNS_ISCSI_SCN_BITMAP_ATTR_ID || 1284 op_len != 12 || 1285 key == NULL || 1286 key->attr_id != ISNS_ISCSI_NAME_ATTR_ID || 1287 key_len != 8 + key->attr_len) { 1288 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1289 goto scn_reg_done; 1290 } 1291 1292 node_name = (uchar_t *)&key->attr_value[0]; 1293 nlen = key->attr_len; 1294 scn = ntohl(*(uint32_t *)&op->attr_value[0]); 1295 1296 ec = add_scn_entry(node_name, nlen, scn); 1297 1298 scn_reg_done: 1299 conn->ec = ec; 1300 1301 if (ec != 0) { 1302 isnslog(LOG_DEBUG, "scn_reg", "error code: %d", ec); 1303 } 1304 1305 return (0); 1306 } 1307 1308 /* 1309 * **************************************************************************** 1310 * 1311 * scn_dereg: 1312 * function which handles the isnsp SCN_DEREG message. 1313 * 1314 * conn - the argument of the connection. 1315 * return - 0: the message requires response. 1316 * 1317 * **************************************************************************** 1318 */ 1319 static int 1320 scn_dereg( 1321 conn_arg_t *conn 1322 ) 1323 { 1324 int ec = 0; 1325 1326 isns_tlv_t *key = conn->in_packet.key; 1327 uint16_t key_len = conn->in_packet.key_len; 1328 1329 uchar_t *node_name; 1330 1331 isnslog(LOG_DEBUG, "scn_dereg", "entered"); 1332 1333 if (key != NULL && 1334 key->attr_len != 0 && 1335 key_len == 8 + key->attr_len && 1336 key->attr_id == ISNS_ISCSI_NAME_ATTR_ID) { 1337 node_name = (uchar_t *)&key->attr_value[0]; 1338 ec = remove_scn_entry(node_name); 1339 } else { 1340 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1341 } 1342 1343 conn->ec = ec; 1344 1345 if (ec != 0) { 1346 isnslog(LOG_DEBUG, "scn_dereg", "error code: %d", ec); 1347 } 1348 1349 return (0); 1350 } 1351 1352 /* 1353 * **************************************************************************** 1354 * 1355 * setup_ddid_lcp: 1356 * setup the lookup control data for looking up the DD object 1357 * by using the dd_id attribute. 1358 * 1359 * lcp - pointer to the lookup control data. 1360 * dd_id- the unique ID of the DD object. 1361 * return - the pointer to the lcp. 1362 * 1363 * **************************************************************************** 1364 */ 1365 #ifndef DEBUG 1366 static 1367 #endif 1368 lookup_ctrl_t * 1369 setup_ddid_lcp( 1370 lookup_ctrl_t *lcp, 1371 uint32_t dd_id 1372 ) 1373 { 1374 lcp->curr_uid = 0; 1375 lcp->type = OBJ_DD; 1376 lcp->id[0] = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID); 1377 lcp->op[0] = OP_INTEGER; 1378 lcp->data[0].ui = dd_id; 1379 lcp->op[1] = 0; 1380 1381 return (lcp); 1382 } 1383 1384 /* 1385 * **************************************************************************** 1386 * 1387 * setup_ddsid_lcp: 1388 * setup the lookup control data for looking up the DD-set object 1389 * by using the dds_id attribute. 1390 * 1391 * lcp - pointer to the lookup control data. 1392 * dds_id - the unique ID of the DD-set object. 1393 * return - the pointer to the lcp. 1394 * 1395 * **************************************************************************** 1396 */ 1397 #ifndef DEBUG 1398 static 1399 #endif 1400 lookup_ctrl_t * 1401 setup_ddsid_lcp( 1402 lookup_ctrl_t *lcp, 1403 uint32_t dds_id 1404 ) 1405 { 1406 lcp->curr_uid = 0; 1407 lcp->type = OBJ_DDS; 1408 lcp->id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID); 1409 lcp->op[0] = OP_INTEGER; 1410 lcp->data[0].ui = dds_id; 1411 lcp->op[1] = 0; 1412 1413 return (lcp); 1414 } 1415 1416 /* 1417 * **************************************************************************** 1418 * 1419 * dd_reg: 1420 * function which handles the isnsp DD_REG message. 1421 * 1422 * conn - the argument of the connection. 1423 * return - 0: the message requires response. 1424 * 1425 * **************************************************************************** 1426 */ 1427 static int 1428 dd_reg( 1429 conn_arg_t *conn 1430 ) 1431 { 1432 int ec = 0; 1433 1434 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1435 isns_tlv_t *source = conn->in_packet.source; 1436 isns_tlv_t *key = conn->in_packet.key; 1437 uint16_t key_len = conn->in_packet.key_len; 1438 isns_tlv_t *op = conn->in_packet.op; 1439 uint16_t op_len = conn->in_packet.op_len; 1440 1441 uint32_t dd_id = 0; 1442 uint8_t *value; 1443 1444 isns_obj_t *dd = NULL; 1445 1446 uchar_t *iscsi_name; 1447 1448 lookup_ctrl_t lc; 1449 isns_assoc_iscsi_t aiscsi; 1450 isns_obj_t *assoc; 1451 isns_attr_t *attr; 1452 1453 uint32_t features; 1454 1455 isnslog(LOG_DEBUG, "dd_reg", "entered"); 1456 1457 iscsi_name = (uchar_t *)&source->attr_value[0]; 1458 if (is_control_node(iscsi_name) == 0) { 1459 ec = ISNS_RSP_SRC_UNAUTHORIZED; 1460 goto dd_reg_done; 1461 } 1462 1463 ec = pdu_reset_rsp(&conn->out_packet.pdu, 1464 &conn->out_packet.pl, 1465 &conn->out_packet.sz); 1466 if (ec != 0) { 1467 goto dd_reg_done; 1468 } 1469 1470 if (op == NULL || 1471 (key != NULL && 1472 (key_len != 12 || 1473 key->attr_id != ISNS_DD_ID_ATTR_ID || 1474 key->attr_len != 4 || 1475 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 || 1476 is_obj_there(setup_ddid_lcp(&lc, dd_id)) == 0))) { 1477 ec = ISNS_RSP_INVALID_REGIS; 1478 goto dd_reg_done; 1479 } 1480 1481 /* message key */ 1482 if (key != NULL && 1483 (ec = rsp_add_tlv(conn, ISNS_DD_ID_ATTR_ID, 4, 1484 (void *)dd_id, 0)) != 0) { 1485 goto dd_reg_done; 1486 } 1487 1488 /* delimiter */ 1489 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, 1490 NULL, 0)) != 0) { 1491 goto dd_reg_done; 1492 } 1493 1494 /* A DDReg message with no Message Key SHALL result in the */ 1495 /* attempted creation of a new Discovery Domain (DD). */ 1496 if (dd_id == 0) { 1497 ec = create_dd_object(op, op_len, &dd); 1498 if (ec == 0) { 1499 ec = register_object(dd, &dd_id, NULL); 1500 if (ec == ERR_NAME_IN_USE) { 1501 ec = ISNS_RSP_INVALID_REGIS; 1502 } 1503 if (ec != 0) { 1504 free_object(dd); 1505 goto dd_reg_done; 1506 } 1507 } else { 1508 goto dd_reg_done; 1509 } 1510 } 1511 1512 /* add the newly created dd to the response */ 1513 if (dd != NULL) { 1514 ec = rsp_add_op(conn, dd); 1515 } 1516 1517 aiscsi.type = OBJ_ASSOC_ISCSI; 1518 aiscsi.puid = dd_id; 1519 1520 while (op_len > 8 && ec == 0) { 1521 value = &op->attr_value[0]; 1522 switch (op->attr_id) { 1523 case ISNS_DD_ID_ATTR_ID: 1524 /* if the DD_ID is included in both the Message Key */ 1525 /* and Operating Attributes, then the DD_ID value */ 1526 /* in the Message Key MUST be the same as the DD_ID */ 1527 /* value in the Operating Attributes. */ 1528 if (dd == NULL) { 1529 if (op->attr_len != 4 || 1530 dd_id != ntohl(*(uint32_t *)value)) { 1531 ec = ISNS_RSP_INVALID_REGIS; 1532 } else { 1533 ec = rsp_add_tlv(conn, 1534 ISNS_DD_ID_ATTR_ID, 4, 1535 (void *)dd_id, 0); 1536 } 1537 } 1538 break; 1539 case ISNS_DD_NAME_ATTR_ID: 1540 /* It is going to modify the DD Symbolic Name. */ 1541 if (dd == NULL) { 1542 if (op->attr_len > 0 && op->attr_len <= 256) { 1543 ec = update_dd_name( 1544 dd_id, 1545 op->attr_len, 1546 (uchar_t *)value); 1547 if (ec == ERR_NAME_IN_USE) { 1548 ec = ISNS_RSP_INVALID_REGIS; 1549 } 1550 } else { 1551 ec = ISNS_RSP_INVALID_REGIS; 1552 } 1553 if (ec == 0) { 1554 ec = rsp_add_tlv(conn, 1555 ISNS_DD_NAME_ATTR_ID, 1556 op->attr_len, (void *)value, 1); 1557 } 1558 } 1559 break; 1560 case ISNS_DD_ISCSI_INDEX_ATTR_ID: 1561 if (op->attr_len == 4) { 1562 /* zero the association object */ 1563 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1564 ISNS_DD_ISCSI_INDEX_ATTR_ID)]; 1565 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID; 1566 attr->len = 4; 1567 attr->value.ui = ntohl(*(uint32_t *)value); 1568 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1569 ISNS_DD_ISCSI_NAME_ATTR_ID)]; 1570 attr->tag = 0; /* clear it */ 1571 attr->value.ptr = NULL; /* clear it */ 1572 assoc = (isns_obj_t *)&aiscsi; 1573 if ((ec = add_dd_member(assoc)) == 1574 ERR_ALREADY_ASSOCIATED) { 1575 ec = 0; 1576 } 1577 if (attr->value.ptr != NULL) { 1578 free(attr->value.ptr); 1579 } 1580 } else { 1581 ec = ISNS_RSP_INVALID_REGIS; 1582 } 1583 if (ec == 0) { 1584 ec = rsp_add_tlv(conn, 1585 ISNS_DD_ISCSI_INDEX_ATTR_ID, 1586 4, (void *)attr->value.ui, 0); 1587 } 1588 break; 1589 case ISNS_DD_ISCSI_NAME_ATTR_ID: 1590 if (op->attr_len > 0 && op->attr_len <= 224) { 1591 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1592 ISNS_DD_ISCSI_NAME_ATTR_ID)]; 1593 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID; 1594 attr->len = op->attr_len; 1595 attr->value.ptr = (uchar_t *)value; 1596 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1597 ISNS_DD_ISCSI_INDEX_ATTR_ID)]; 1598 attr->tag = 0; /* clear it */ 1599 assoc = (isns_obj_t *)&aiscsi; 1600 if ((ec = add_dd_member(assoc)) == 1601 ERR_ALREADY_ASSOCIATED) { 1602 ec = 0; 1603 } 1604 } else { 1605 ec = ISNS_RSP_INVALID_REGIS; 1606 } 1607 if (ec == 0) { 1608 ec = rsp_add_tlv(conn, 1609 ISNS_DD_ISCSI_NAME_ATTR_ID, 1610 op->attr_len, (void *)value, 1); 1611 } 1612 break; 1613 case ISNS_DD_FC_PORT_NAME_ATTR_ID: 1614 case ISNS_DD_PORTAL_INDEX_ATTR_ID: 1615 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID: 1616 case ISNS_DD_PORTAL_PORT_ATTR_ID: 1617 ec = ISNS_RSP_REGIS_NOT_SUPPORTED; 1618 break; 1619 case ISNS_DD_FEATURES_ATTR_ID: 1620 /* It is going to modify the DD Symbolic Name. */ 1621 if (dd == NULL) { 1622 if (op->attr_len == 4) { 1623 features = ntohl(*(uint32_t *)value); 1624 ec = update_dd_features( 1625 dd_id, features); 1626 } else { 1627 ec = ISNS_RSP_INVALID_REGIS; 1628 } 1629 if (ec == 0) { 1630 ec = rsp_add_tlv(conn, 1631 ISNS_DD_FEATURES_ATTR_ID, 1632 4, (void *)features, 0); 1633 } 1634 } 1635 break; 1636 default: 1637 ec = ISNS_RSP_INVALID_REGIS; 1638 break; 1639 } 1640 1641 NEXT_TLV(op, op_len); 1642 } 1643 1644 dd_reg_done: 1645 conn->ec = ec; 1646 1647 if (ec != 0) { 1648 isnslog(LOG_DEBUG, "dd_reg", "error code: %d", ec); 1649 } 1650 1651 return (0); 1652 } 1653 1654 /* 1655 * **************************************************************************** 1656 * 1657 * dds_reg: 1658 * function which handles the isnsp DDS_REG message. 1659 * 1660 * conn - the argument of the connection. 1661 * return - 0: the message requires response. 1662 * 1663 * **************************************************************************** 1664 */ 1665 static int 1666 dds_reg( 1667 conn_arg_t *conn 1668 ) 1669 { 1670 int ec = 0; 1671 1672 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1673 isns_tlv_t *source = conn->in_packet.source; 1674 isns_tlv_t *key = conn->in_packet.key; 1675 uint16_t key_len = conn->in_packet.key_len; 1676 isns_tlv_t *op = conn->in_packet.op; 1677 uint16_t op_len = conn->in_packet.op_len; 1678 1679 uint32_t dds_id = 0; 1680 uint8_t *value; 1681 1682 isns_obj_t *dds = NULL; 1683 1684 uchar_t *iscsi_name; 1685 1686 lookup_ctrl_t lc; 1687 isns_assoc_dd_t add; 1688 isns_obj_t *assoc; 1689 isns_attr_t *attr; 1690 1691 uint32_t code; 1692 1693 isnslog(LOG_DEBUG, "dds_reg", "entered"); 1694 1695 iscsi_name = (uchar_t *)&source->attr_value[0]; 1696 if (is_control_node(iscsi_name) == 0) { 1697 ec = ISNS_RSP_SRC_UNAUTHORIZED; 1698 goto dds_reg_done; 1699 } 1700 1701 ec = pdu_reset_rsp(&conn->out_packet.pdu, 1702 &conn->out_packet.pl, 1703 &conn->out_packet.sz); 1704 if (ec != 0) { 1705 goto dds_reg_done; 1706 } 1707 1708 if (op == NULL || 1709 (key != NULL && 1710 (key_len != 12 || 1711 key->attr_id != ISNS_DD_SET_ID_ATTR_ID || 1712 key->attr_len != 4 || 1713 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 || 1714 is_obj_there(setup_ddsid_lcp(&lc, dds_id)) == 0))) { 1715 ec = ISNS_RSP_INVALID_REGIS; 1716 goto dds_reg_done; 1717 } 1718 1719 /* message key */ 1720 if (key != NULL && 1721 (ec = rsp_add_tlv(conn, ISNS_DD_SET_ID_ATTR_ID, 4, 1722 (void *)dds_id, 0)) != 0) { 1723 goto dds_reg_done; 1724 } 1725 1726 /* delimiter */ 1727 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, 1728 NULL, 0)) != 0) { 1729 goto dds_reg_done; 1730 } 1731 1732 /* A DDSReg message with no Message Key SHALL result in the */ 1733 /* attempted creation of a new Discovery Domain (DD). */ 1734 if (dds_id == 0) { 1735 ec = create_dds_object(op, op_len, &dds); 1736 if (ec == 0) { 1737 ec = register_object(dds, &dds_id, NULL); 1738 if (ec == ERR_NAME_IN_USE) { 1739 ec = ISNS_RSP_INVALID_REGIS; 1740 } 1741 if (ec != 0) { 1742 free_object(dds); 1743 goto dds_reg_done; 1744 } 1745 } else { 1746 goto dds_reg_done; 1747 } 1748 } 1749 1750 /* add the newly created dd to the response */ 1751 if (dds != NULL) { 1752 ec = rsp_add_op(conn, dds); 1753 } 1754 1755 add.type = OBJ_ASSOC_DD; 1756 add.puid = dds_id; 1757 1758 while (op_len > 8 && ec == 0) { 1759 value = &op->attr_value[0]; 1760 switch (op->attr_id) { 1761 case ISNS_DD_SET_ID_ATTR_ID: 1762 /* if the DDS_ID is included in both the Message Key */ 1763 /* and Operating Attributes, then the DDS_ID value */ 1764 /* in the Message Key MUST be the same as the DDS_ID */ 1765 /* value in the Operating Attributes. */ 1766 if (dds == NULL) { 1767 if (op->attr_len != 4 || 1768 dds_id != ntohl(*(uint32_t *)value)) { 1769 ec = ISNS_RSP_INVALID_REGIS; 1770 } else { 1771 ec = rsp_add_tlv(conn, 1772 ISNS_DD_SET_ID_ATTR_ID, 1773 4, (void *)dds_id, 0); 1774 } 1775 } 1776 break; 1777 case ISNS_DD_SET_NAME_ATTR_ID: 1778 /* It is going to modify the DD Symbolic Name. */ 1779 if (dds == NULL) { 1780 if (op->attr_len > 0 && op->attr_len <= 256) { 1781 ec = update_dds_name( 1782 dds_id, 1783 op->attr_len, 1784 (uchar_t *)value); 1785 if (ec == ERR_NAME_IN_USE) { 1786 ec = ISNS_RSP_INVALID_REGIS; 1787 } 1788 } else { 1789 ec = ISNS_RSP_INVALID_REGIS; 1790 } 1791 if (ec == 0) { 1792 ec = rsp_add_tlv(conn, 1793 ISNS_DD_SET_NAME_ATTR_ID, 1794 op->attr_len, (void *)value, 1); 1795 } 1796 } 1797 break; 1798 case ISNS_DD_SET_STATUS_ATTR_ID: 1799 /* It is going to modify the DD Symbolic Name. */ 1800 if (dds == NULL) { 1801 if (op->attr_len == 4) { 1802 code = ntohl(*(uint32_t *)value); 1803 ec = update_dds_status( 1804 dds_id, code); 1805 } else { 1806 ec = ISNS_RSP_INVALID_REGIS; 1807 } 1808 if (ec == 0) { 1809 ec = rsp_add_tlv(conn, 1810 ISNS_DD_SET_STATUS_ATTR_ID, 1811 4, (void *)code, 0); 1812 } 1813 } 1814 break; 1815 case ISNS_DD_ID_ATTR_ID: 1816 if (op->attr_len == 4) { 1817 /* zero the association object */ 1818 attr = &add.attrs[ATTR_INDEX_ASSOC_DD( 1819 ISNS_DD_ID_ATTR_ID)]; 1820 attr->tag = ISNS_DD_ID_ATTR_ID; 1821 attr->len = 4; 1822 attr->value.ui = ntohl(*(uint32_t *)value); 1823 assoc = (isns_obj_t *)&add; 1824 if ((ec = add_dds_member(assoc)) == 1825 ERR_ALREADY_ASSOCIATED) { 1826 ec = 0; 1827 } 1828 } else { 1829 ec = ISNS_RSP_INVALID_REGIS; 1830 } 1831 if (ec == 0) { 1832 ec = rsp_add_tlv(conn, 1833 ISNS_DD_ID_ATTR_ID, 4, 1834 (void *)attr->value.ui, 0); 1835 } 1836 break; 1837 default: 1838 ec = ISNS_RSP_INVALID_REGIS; 1839 break; 1840 } 1841 1842 NEXT_TLV(op, op_len); 1843 } 1844 1845 dds_reg_done: 1846 conn->ec = ec; 1847 1848 if (ec != 0) { 1849 isnslog(LOG_DEBUG, "dds_reg", "error code: %d", ec); 1850 } 1851 1852 return (0); 1853 } 1854 1855 /* 1856 * **************************************************************************** 1857 * 1858 * dd_dereg: 1859 * function which handles the isnsp DD_DEREG message. 1860 * 1861 * conn - the argument of the connection. 1862 * return - 0: the message requires response. 1863 * 1864 * **************************************************************************** 1865 */ 1866 static int 1867 dd_dereg( 1868 conn_arg_t *conn 1869 ) 1870 { 1871 int ec = 0; 1872 1873 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1874 isns_tlv_t *source = conn->in_packet.source; 1875 isns_tlv_t *key = conn->in_packet.key; 1876 uint16_t key_len = conn->in_packet.key_len; 1877 isns_tlv_t *op = conn->in_packet.op; 1878 uint16_t op_len = conn->in_packet.op_len; 1879 1880 uint32_t dd_id; 1881 uint8_t *value; 1882 1883 uchar_t *iscsi_name; 1884 1885 isns_assoc_iscsi_t aiscsi; 1886 isns_obj_t *assoc; 1887 isns_attr_t *attr; 1888 1889 isnslog(LOG_DEBUG, "dd_dereg", "entered"); 1890 1891 iscsi_name = (uchar_t *)&source->attr_value[0]; 1892 if (is_control_node(iscsi_name) == 0) { 1893 ec = ISNS_RSP_SRC_UNAUTHORIZED; 1894 goto dd_dereg_done; 1895 } 1896 1897 if (key == NULL || 1898 key_len != 12 || 1899 key->attr_id != ISNS_DD_ID_ATTR_ID || 1900 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) { 1901 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1902 goto dd_dereg_done; 1903 } 1904 1905 if (op == NULL) { 1906 ec = remove_dd_object(dd_id); 1907 } else { 1908 aiscsi.type = OBJ_ASSOC_ISCSI; 1909 aiscsi.puid = dd_id; 1910 1911 while (op_len > 8 && ec == 0) { 1912 value = &op->attr_value[0]; 1913 switch (op->attr_id) { 1914 case ISNS_DD_ISCSI_INDEX_ATTR_ID: 1915 /* zero the association object */ 1916 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1917 ISNS_DD_ISCSI_INDEX_ATTR_ID)]; 1918 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID; 1919 attr->len = 4; 1920 attr->value.ui = ntohl(*(uint32_t *)value); 1921 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1922 ISNS_DD_ISCSI_NAME_ATTR_ID)]; 1923 attr->tag = 0; /* clear it */ 1924 attr->value.ptr = NULL; /* clear it */ 1925 assoc = (isns_obj_t *)&aiscsi; 1926 if ((ec = remove_dd_member(assoc)) == 1927 ERR_NO_SUCH_ASSOCIATION) { 1928 ec = 0; 1929 } 1930 if (attr->value.ptr != NULL) { 1931 free(attr->value.ptr); 1932 } 1933 break; 1934 case ISNS_DD_ISCSI_NAME_ATTR_ID: 1935 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1936 ISNS_DD_ISCSI_NAME_ATTR_ID)]; 1937 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID; 1938 attr->len = op->attr_len; 1939 attr->value.ptr = (uchar_t *)value; 1940 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI( 1941 ISNS_DD_ISCSI_INDEX_ATTR_ID)]; 1942 attr->tag = 0; /* clear it */ 1943 assoc = (isns_obj_t *)&aiscsi; 1944 if ((ec = remove_dd_member(assoc)) == 1945 ERR_NO_SUCH_ASSOCIATION) { 1946 ec = 0; 1947 } 1948 break; 1949 case ISNS_DD_FC_PORT_NAME_ATTR_ID: 1950 case ISNS_DD_PORTAL_INDEX_ATTR_ID: 1951 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID: 1952 case ISNS_DD_PORTAL_PORT_ATTR_ID: 1953 ec = ISNS_RSP_REGIS_NOT_SUPPORTED; 1954 break; 1955 default: 1956 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1957 break; 1958 } 1959 1960 NEXT_TLV(op, op_len); 1961 } 1962 } 1963 1964 dd_dereg_done: 1965 conn->ec = ec; 1966 1967 if (ec != 0) { 1968 isnslog(LOG_DEBUG, "dd_dereg", "error code: %d", ec); 1969 } 1970 1971 return (0); 1972 } 1973 1974 /* 1975 * **************************************************************************** 1976 * 1977 * dds_dereg: 1978 * function which handles the isnsp DDS_DEREG message. 1979 * 1980 * conn - the argument of the connection. 1981 * return - 0: the message requires response. 1982 * 1983 * **************************************************************************** 1984 */ 1985 static int 1986 dds_dereg( 1987 conn_arg_t *conn 1988 ) 1989 { 1990 int ec = 0; 1991 1992 /* isns_pdu_t *pdu = conn->in_packet.pdu; */ 1993 isns_tlv_t *source = conn->in_packet.source; 1994 isns_tlv_t *key = conn->in_packet.key; 1995 uint16_t key_len = conn->in_packet.key_len; 1996 isns_tlv_t *op = conn->in_packet.op; 1997 uint16_t op_len = conn->in_packet.op_len; 1998 1999 uint32_t dds_id; 2000 uint32_t uid; 2001 uint8_t *value; 2002 2003 uchar_t *iscsi_name; 2004 2005 isnslog(LOG_DEBUG, "dds_dereg", "entered"); 2006 2007 iscsi_name = (uchar_t *)&source->attr_value[0]; 2008 if (is_control_node(iscsi_name) == 0) { 2009 ec = ISNS_RSP_SRC_UNAUTHORIZED; 2010 goto dds_dereg_done; 2011 } 2012 2013 if (key == NULL || 2014 key_len != 12 || 2015 key->attr_id != ISNS_DD_SET_ID_ATTR_ID || 2016 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) { 2017 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2018 goto dds_dereg_done; 2019 } 2020 2021 if (op == NULL) { 2022 ec = remove_dds_object(dds_id); 2023 } else { 2024 while (op_len > 8 && ec == 0) { 2025 value = &op->attr_value[0]; 2026 if (op->attr_id == ISNS_DD_ID_ATTR_ID) { 2027 uid = ntohl(*(uint32_t *)value); 2028 if ((ec = remove_dds_member(dds_id, uid)) == 2029 ERR_NO_SUCH_ASSOCIATION) { 2030 ec = 0; 2031 } 2032 } else { 2033 ec = ISNS_RSP_MSG_FORMAT_ERROR; 2034 } 2035 2036 NEXT_TLV(op, op_len); 2037 } 2038 } 2039 2040 dds_dereg_done: 2041 conn->ec = ec; 2042 2043 if (ec != 0) { 2044 isnslog(LOG_DEBUG, "dds_dereg", "error code: %d", ec); 2045 } 2046 2047 return (0); 2048 } 2049 2050 /* 2051 * **************************************************************************** 2052 * 2053 * msg_error: 2054 * function which handles any unknown isnsp messages or the 2055 * messages which are not supported. 2056 * 2057 * conn - the argument of the connection. 2058 * return - 0: the message requires response. 2059 * 2060 * **************************************************************************** 2061 */ 2062 static int 2063 msg_error( 2064 /* LINTED E_FUNC_ARG_UNUSED */ 2065 conn_arg_t *conn 2066 ) 2067 { 2068 return (0); 2069 } 2070 2071 /* 2072 * **************************************************************************** 2073 * 2074 * isns_response_ec: 2075 * send the response message to the client with error code. 2076 * 2077 * so - the socket descriptor. 2078 * pdu - the received pdu. 2079 * ec - the error code which is being responsed. 2080 * return - status of the sending operation. 2081 * 2082 * **************************************************************************** 2083 */ 2084 static int 2085 isns_response_ec( 2086 int so, 2087 isns_pdu_t *pdu, 2088 int ec 2089 ) 2090 { 2091 int status; 2092 2093 uint8_t buff[sizeof (isns_pdu_t) + 8]; 2094 2095 isns_pdu_t *rsp = (isns_pdu_t *)&buff; 2096 isns_resp_t *resp = (isns_resp_t *)rsp->payload; 2097 size_t pl = 4; 2098 2099 rsp->version = htons((uint16_t)ISNSP_VERSION); 2100 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK); 2101 rsp->xid = htons(pdu->xid); 2102 resp->status = htonl(ec); 2103 2104 status = isns_send_pdu(so, rsp, pl); 2105 2106 return (status); 2107 } 2108 2109 /* 2110 * **************************************************************************** 2111 * 2112 * isns_response: 2113 * send the response message to the client. 2114 * 2115 * conn - the argument of the connection. 2116 * return - status of the sending operation. 2117 * 2118 * **************************************************************************** 2119 */ 2120 int 2121 isns_response( 2122 conn_arg_t *conn 2123 ) 2124 { 2125 int status; 2126 2127 int so = conn->so; 2128 int ec = conn->ec; 2129 isns_pdu_t *pdu = conn->in_packet.pdu; 2130 isns_pdu_t *rsp = conn->out_packet.pdu; 2131 size_t pl = conn->out_packet.pl; 2132 2133 if (rsp != NULL) { 2134 rsp->version = htons((uint16_t)ISNSP_VERSION); 2135 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK); 2136 rsp->xid = htons(pdu->xid); 2137 (void) pdu_update_code(rsp, &pl, ec); 2138 status = isns_send_pdu(so, rsp, pl); 2139 } else { 2140 status = isns_response_ec(so, pdu, ec); 2141 } 2142 2143 return (status); 2144 } 2145