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