1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <strings.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <dirent.h> 32 #include <assert.h> 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/stat.h> 36 #include <sys/socket.h> 37 #include <inttypes.h> 38 #include <netinet/in.h> 39 #include <arpa/inet.h> 40 #include <errno.h> 41 #include <utility.h> 42 #include <fcntl.h> 43 #include <syslog.h> 44 45 #include <iscsitgt_impl.h> 46 #include "target.h" 47 #include "utility.h" 48 #include "errcode.h" 49 #include "isns_client.h" 50 #include <sys/scsi/generic/commands.h> 51 #include "mgmt_scf.h" 52 #include "t10_spc.h" 53 54 #define CRC32_STR "CRC32C" 55 #define NONE_STR "None" 56 57 static thick_provo_t *thick_head, 58 *thick_tail; 59 pthread_mutex_t thick_mutex; 60 61 static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name); 62 static Boolean_t util_create_guid_naa(char **guid); 63 64 void 65 util_init() 66 { 67 (void) pthread_mutex_init(&thick_mutex, NULL); 68 } 69 70 /* 71 * []---- 72 * | check_access -- see if the requesting initiator is in the ACL 73 * | 74 * | Optionally will also check to see if this initiator requires 75 * | authentication. 76 * []---- 77 */ 78 Boolean_t 79 check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap) 80 { 81 tgt_node_t *acl; 82 tgt_node_t *inode = NULL; 83 tgt_node_t *tgt_initiator = NULL; 84 char *dummy; 85 Boolean_t valid = False; 86 Boolean_t found_chap = False; 87 Boolean_t access = False; 88 89 /* 90 * If ISNS is enable check for access privilege from isns server 91 */ 92 if (isns_enabled() == True) { 93 if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &dummy) 94 == False) { 95 return (False); 96 } 97 access = isns_qry_initiator(dummy, initiator_name); 98 free(dummy); 99 if (req_chap == False) { 100 return (access); 101 } 102 103 /* Need to check if CHAP is needed for initiator */ 104 while ((inode = tgt_node_next_child(main_config, 105 XML_ELEMENT_INIT, inode)) != NULL) { 106 if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) 107 == True) { 108 if (strcmp(dummy, initiator_name) == 0) { 109 free(dummy); 110 if (tgt_find_value_str(inode, 111 XML_ELEMENT_CHAPSECRET, &dummy) 112 == True) { 113 free(dummy); 114 found_chap = True; 115 break; 116 } 117 } 118 } 119 } 120 if (access == True) { 121 if ((req_chap == True) && (found_chap == True)) 122 access = False; 123 } 124 return (access); 125 } 126 127 /* 128 * If there's no ACL for this target everyone has access. 129 */ 130 if ((acl = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL) 131 return (True); 132 133 /* 134 * Find the local initiator name and also save the knowledge 135 * if the initiator had a CHAP secret. 136 */ 137 inode = NULL; 138 while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT, 139 inode)) != NULL) { 140 if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) == 141 True) { 142 if (strcmp(dummy, initiator_name) == 0) { 143 free(dummy); 144 if (tgt_find_value_str(inode, 145 XML_ELEMENT_CHAPSECRET, &dummy) == True) { 146 free(dummy); 147 found_chap = True; 148 } 149 break; 150 } else { 151 free(dummy); 152 } 153 } 154 } 155 156 if ((acl != NULL) && (inode == NULL)) 157 return (False); 158 159 while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT, 160 tgt_initiator)) != NULL) { 161 162 if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) { 163 valid = True; 164 break; 165 } 166 } 167 168 if (valid == True) { 169 170 /* 171 * If req_chap is True it means the login code hasn't gone 172 * through the authentication phase and it's trying to 173 * determine if the initiator should have done so. If 174 * we find a CHAP-secret then this routine will fail. 175 * No CHAP-secret for an initiator just means that a 176 * simple ACL list is used. This can be spoofed easily 177 * enough and is mainly used to limit the number of 178 * targets an initiator would see. 179 */ 180 if ((req_chap == True) && (found_chap == True)) 181 valid = False; 182 } 183 184 return (valid); 185 } 186 187 /* 188 * []---- 189 * | convert_local_tpgt -- Convert a local tpgt name to real addresses 190 * | 191 * | To simplify the configuration files targets only have a target portal 192 * | group tag string(s) associated. In the main configuration file there's 193 * | a tpgt element which has one or more ip-address elements. So the tag 194 * | is located and the actual data is inserted into the outgoing stream. 195 * []---- 196 */ 197 static Boolean_t 198 convert_local_tpgt(char **text, int *text_length, char *local_tpgt) 199 { 200 tgt_node_t *tpgt = NULL; 201 tgt_node_t *x; 202 char buf[80]; 203 char ipaddr[4]; 204 205 while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT, 206 tpgt)) != NULL) { 207 if (strcmp(tpgt->x_value, local_tpgt) == 0) { 208 209 /* 210 * The only children of the tpgt element are 211 * ip-address elements. The value of each element is 212 * the string we need to use. So, we don't need to 213 * check the node's name to see if this is correct or 214 * not. 215 */ 216 if ((tpgt = tgt_node_next(tpgt, XML_ELEMENT_IPADDRLIST, 217 NULL)) == NULL) { 218 return (False); 219 } 220 221 x = NULL; 222 while ((x = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, x)) 223 != NULL) { 224 if (inet_pton(AF_INET, x->x_value, &ipaddr) 225 == 1) { 226 /* 227 * Valid IPv4 address 228 */ 229 (void) snprintf(buf, sizeof (buf), 230 231 "%s,%s", x->x_value, local_tpgt); 232 } else { 233 /* 234 * Invalid IPv4 address 235 * try with brackets (RFC2732) 236 */ 237 (void) snprintf(buf, sizeof (buf), 238 "[%s],%s", x->x_value, local_tpgt); 239 } 240 (void) add_text(text, text_length, 241 "TargetAddress", buf); 242 } 243 break; 244 } 245 } 246 247 return (True); 248 } 249 250 /* 251 * []---- 252 * | add_target_address -- find and add any target address information 253 * []---- 254 */ 255 static void 256 add_target_address(iscsi_conn_t *c, char **text, int *text_length, 257 tgt_node_t *targ) 258 { 259 tgt_node_t *tpgt_list; 260 tgt_node_t *tpgt = NULL; 261 struct sockaddr_in *sp4; 262 struct sockaddr_in6 *sp6; 263 /* 264 * 7 is enough room for the largest TPGT of "65536", the ',' and a NULL 265 */ 266 char buf[INET6_ADDRSTRLEN + 7]; 267 char net_buf[INET6_ADDRSTRLEN]; 268 269 if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, 270 NULL)) == NULL) { 271 if_target_address(text, text_length, 272 (struct sockaddr *)&c->c_target_sockaddr); 273 return; 274 } 275 276 while ((tpgt = tgt_node_next_child(tpgt_list, XML_ELEMENT_TPGT, 277 tpgt)) != NULL) { 278 if (convert_local_tpgt(text, text_length, tpgt->x_value) == 279 False) { 280 if (c->c_target_sockaddr.ss_family == AF_INET) { 281 sp4 = (struct sockaddr_in *) 282 &c->c_target_sockaddr; 283 (void) snprintf(buf, sizeof (buf), "%s,%s", 284 inet_ntop(sp4->sin_family, 285 (void *)&sp4->sin_addr, 286 net_buf, sizeof (net_buf)), 287 tpgt->x_value); 288 } else { 289 sp6 = (struct sockaddr_in6 *) 290 &c->c_target_sockaddr; 291 (void) snprintf(buf, sizeof (buf), "[%s],%s", 292 inet_ntop(sp6->sin6_family, 293 (void *)&sp6->sin6_addr, 294 net_buf, sizeof (net_buf)), 295 tpgt->x_value); 296 } 297 (void) add_text(text, text_length, "TargetAddress", 298 buf); 299 } 300 } 301 } 302 303 /* 304 * []---- 305 * | add_targets -- add TargetName and TargetAddress to text argument 306 * | 307 * | Add targets which this initiator is allowed to see based on 308 * | the access_list associated with a target. If a target doesn't 309 * | have an access list then let everyone see it. 310 * []---- 311 */ 312 static Boolean_t 313 add_targets(iscsi_conn_t *c, char **text, int *text_length) 314 { 315 tgt_node_t *targ = NULL; 316 Boolean_t rval = True; 317 char *targ_name = NULL; 318 319 while ((rval == True) && ((targ = tgt_node_next_child(targets_config, 320 XML_ELEMENT_TARG, targ)) != NULL)) { 321 322 if (check_access(targ, c->c_sess->s_i_name, False) == True) { 323 324 if (tgt_find_value_str(targ, XML_ELEMENT_INAME, 325 &targ_name) == False) { 326 rval = False; 327 break; 328 } 329 queue_prt(c->c_mgmtq, Q_CONN_LOGIN, 330 "CON%x %24s = %s\n", c->c_num, "TargetName", 331 targ_name); 332 333 (void) add_text(text, text_length, "TargetName", 334 targ_name); 335 free(targ_name); 336 add_target_address(c, text, text_length, targ); 337 } 338 } 339 return (rval); 340 } 341 342 /* 343 * []---- 344 * | add_text -- Add new name/value pair to possibly existing string 345 * []---- 346 */ 347 Boolean_t 348 add_text(char **text, int *current_length, char *name, char *val) 349 { 350 int dlen = *current_length; 351 int plen; 352 char *p; 353 354 /* 355 * Length is 'name' + separator + 'value' + NULL 356 */ 357 plen = strlen(name) + 1 + strlen(val) + 1; 358 359 if (dlen) { 360 if ((p = (char *)realloc(*text, dlen + plen)) == NULL) 361 return (False); 362 } else { 363 if ((p = (char *)malloc(plen)) == NULL) 364 return (False); 365 } 366 367 *text = p; 368 p = *text + dlen; 369 370 (void) snprintf(p, plen, "%s%c%s", name, ISCSI_TEXT_SEPARATOR, val); 371 *current_length = dlen + plen; 372 373 return (True); 374 } 375 376 static void 377 send_named_msg(iscsi_conn_t *c, msg_type_t t, char *name) 378 { 379 target_queue_t *q = queue_alloc(); 380 msg_t *m; 381 name_request_t n; 382 383 n.nr_q = q; 384 n.nr_name = name; 385 386 queue_message_set(c->c_sessq, 0, t, &n); 387 m = queue_message_get(q); 388 queue_message_free(m); 389 queue_free(q, NULL); 390 } 391 392 static Boolean_t 393 parse_digest_vals(Boolean_t *bp, char *name, char *val, char **text, int *len) 394 { 395 Boolean_t rval; 396 397 /* 398 * It's the initiators data so we'll allow them 399 * to determine if CRC checks should be enabled 400 * or not. So, look at the first token, which 401 * declares their preference, and use that. 402 */ 403 if (strncmp(val, CRC32_STR, strlen(CRC32_STR)) == 0) { 404 *bp = True; 405 rval = add_text(text, len, name, CRC32_STR); 406 } else if (strncmp(val, NONE_STR, strlen(NONE_STR)) == 0) { 407 *bp = False; 408 rval = add_text(text, len, name, NONE_STR); 409 } else { 410 *bp = False; 411 rval = add_text(text, len, name, "Reject"); 412 } 413 414 return (rval); 415 } 416 417 /* 418 * []---- 419 * | parse_text -- receive text information from initiator and parse 420 * | 421 * | Read in the current data based on the amount which the login PDU says 422 * | should be available. Add it to the end of previous data if it exists. 423 * | Previous data would be from a PDU which had the 'C' bit set and was 424 * | stored in the connection. 425 * | 426 * | Once values for parameter name has been selected store outgoing string 427 * | in text message for response. 428 * | 429 * | If errcode is non-NULL the appropriate login error code will be 430 * | stored. 431 * []---- 432 */ 433 Boolean_t 434 parse_text(iscsi_conn_t *c, int dlen, char **text, int *text_length, 435 int *errcode) 436 { 437 char *p = NULL; 438 char *n; 439 char *cur_pair; 440 char param_rsp[32]; 441 int plen; /* pair length */ 442 Boolean_t rval = True; 443 char *target_name = NULL; 444 char *initiator_name = NULL; 445 char param_buf[16]; 446 447 if ((p = (char *)malloc(dlen)) == NULL) 448 return (False); 449 450 /* 451 * Read in data to buffer. 452 */ 453 if (read(c->c_fd, p, dlen) != dlen) { 454 free(p); 455 return (False); 456 } 457 458 queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x Available text size %d\n", 459 c->c_num, dlen); 460 461 /* 462 * Read in and toss any pad data 463 */ 464 if (dlen % ISCSI_PAD_WORD_LEN) { 465 char junk[ISCSI_PAD_WORD_LEN]; 466 int pad_len = ISCSI_PAD_WORD_LEN - (dlen % ISCSI_PAD_WORD_LEN); 467 468 if (read(c->c_fd, junk, pad_len) != pad_len) { 469 free(p); 470 return (False); 471 } 472 } 473 474 if (c->c_text_area != NULL) { 475 if ((n = (char *)realloc(c->c_text_area, 476 c->c_text_len + dlen)) == NULL) { 477 free(p); 478 return (False); 479 } 480 bcopy(p, n + c->c_text_len, dlen); 481 482 /* 483 * No longer need the space allocated to 'p' since it 484 * will point to the aggregated area of all data. 485 */ 486 free(p); 487 488 /* 489 * Point 'p' to this new area for parsing and save the 490 * combined length in dlen. 491 */ 492 p = n; 493 dlen += c->c_text_len; 494 495 /* 496 * Clear the indication that space has been allocated 497 */ 498 c->c_text_area = NULL; 499 c->c_text_len = 0; 500 } 501 502 /* 503 * At this point 'p' points to the name/value parameters. Need 504 * to cycle through each pair. 505 */ 506 n = p; 507 while (dlen > 0) { 508 cur_pair = n; 509 510 plen = strlen(n); 511 if ((n = strchr(cur_pair, ISCSI_TEXT_SEPARATOR)) == NULL) { 512 if (errcode != NULL) 513 *errcode = 514 (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) | 515 ISCSI_LOGIN_STATUS_INIT_ERR; 516 rval = False; 517 break; 518 } else 519 *n++ = '\0'; 520 521 queue_prt(c->c_mgmtq, Q_CONN_LOGIN, "CON%x %-24s = %s\n", 522 c->c_num, cur_pair, n); 523 524 /* 525 * At this point, 'cur_pair' points at the name and 'n' 526 * points at the value. 527 */ 528 529 /* 530 * []--------------------------------------------------[] 531 * | The order of parameters processed matches the | 532 * | the RFC in section 12. | 533 * []--------------------------------------------------[] 534 */ 535 /* 536 * 12.1 -- HeaderDigest 537 * Negotiated 538 */ 539 if (strcmp("HeaderDigest", cur_pair) == 0) { 540 541 rval = parse_digest_vals(&c->c_header_digest, 542 cur_pair, n, text, text_length); 543 544 /* 545 * 12.1 -- DataDigest 546 * Negotiated 547 */ 548 } else if (strcmp("DataDigest", cur_pair) == 0) { 549 550 rval = parse_digest_vals(&c->c_data_digest, cur_pair, 551 n, text, text_length); 552 553 /* 554 * 12.2 -- MaxConnections 555 * Negotiated 556 */ 557 } else if (strcmp("MaxConnections", cur_pair) == 0) { 558 559 /* ---- To be fixed ---- */ 560 c->c_max_connections = 1; 561 (void) snprintf(param_rsp, sizeof (param_rsp), 562 "%d", c->c_max_connections); 563 rval = add_text(text, text_length, 564 cur_pair, param_rsp); 565 566 /* 567 * 12.3 -- SendTargets 568 * Declarative 569 */ 570 } else if (strcmp("SendTargets", cur_pair) == 0) { 571 572 if ((c->c_sess->s_type != SessionDiscovery) && 573 (strcmp("All", n) == 0)) { 574 rval = add_text(text, text_length, cur_pair, 575 "Irrelevant"); 576 } else { 577 rval = add_targets(c, text, text_length); 578 } 579 580 /* 581 * 12.4 -- TargetName 582 * Declarative 583 */ 584 } else if (strcmp("TargetName", cur_pair) == 0) { 585 586 send_named_msg(c, msg_target_name, n); 587 target_name = n; 588 589 /* 590 * 12.5 -- IntiatorName 591 * Declarative 592 */ 593 } else if (strcmp("InitiatorName", cur_pair) == 0) { 594 595 send_named_msg(c, msg_initiator_name, n); 596 initiator_name = n; 597 598 /* ---- Section 12.6 is handled within TargetName ---- */ 599 600 /* 601 * 12.7 -- InitiatorAlias 602 * Declarative 603 */ 604 } else if (strcmp("InitiatorAlias", cur_pair) == 0) { 605 606 send_named_msg(c, msg_initiator_alias, n); 607 608 /* 609 * Sections 12.8 (TargetAddress) and 12.9 610 * (TargetPortalGroupTag) are handled during the SendTargets 611 * processing. 612 */ 613 614 /* 615 * 12.10 -- IntialR2T 616 * Negotiated 617 */ 618 } else if (strcmp("InitialR2T", cur_pair) == 0) { 619 620 c->c_initialR2T = True; 621 rval = add_text(text, text_length, cur_pair, "Yes"); 622 623 /* 624 * 12.11 -- ImmediateData 625 * Negotiated 626 */ 627 } else if (strcmp("ImmediateData", cur_pair) == 0) { 628 629 /* 630 * Since we can handle immediate data without 631 * a problem just echo back what the initiator 632 * sends. If the initiator decides to violate 633 * the spec by sending immediate data even though 634 * they've disabled it, it's their problem and 635 * we'll deal with the data. 636 */ 637 c->c_immediate_data = strcmp(n, "No") ? True : False; 638 rval = add_text(text, text_length, cur_pair, n); 639 640 /* 641 * 12.12 -- MaxRecvDataSegmentLength 642 * Declarative 643 */ 644 } else if (strcmp("MaxRecvDataSegmentLength", cur_pair) == 0) { 645 646 c->c_max_recv_data = strtol(n, NULL, 0); 647 rval = add_text(text, text_length, cur_pair, n); 648 649 /* 650 * 12.13 -- MaxBurstLength 651 * Negotiated 652 */ 653 } else if (strcmp("MaxBurstLength", cur_pair) == 0) { 654 655 c->c_max_burst_len = strtol(n, NULL, 0); 656 rval = add_text(text, text_length, cur_pair, n); 657 658 /* 659 * 12.14 -- FirstBurstLength 660 * Negotiated 661 */ 662 } else if (strcmp("FirstBurstLength", cur_pair) == 0) { 663 664 /* 665 * We can handle anything the initiator wishes 666 * to shove in our direction. So, store the value 667 * in case we ever wish to validate input data, 668 * but there's no real need to do so. 669 */ 670 c->c_first_burst_len = strtol(n, NULL, 0); 671 rval = add_text(text, text_length, cur_pair, n); 672 673 /* 674 * 12.15 DefaultTime2Wait 675 * Negotiated 676 */ 677 } else if (strcmp("DefaultTime2Wait", cur_pair) == 0) { 678 679 c->c_default_time_2_wait = strtol(n, NULL, 0); 680 rval = add_text(text, text_length, cur_pair, n); 681 682 /* 683 * 12.16 -- DefaultTime2Retain 684 * Negotiated 685 */ 686 } else if (strcmp("DefaultTime2Retain", cur_pair) == 0) { 687 688 c->c_default_time_2_retain = strtol(n, NULL, 0); 689 rval = add_text(text, text_length, cur_pair, n); 690 691 /* 692 * 12.17 -- MaxOutstandingR2T 693 * Negotiated 694 */ 695 } else if (strcmp("MaxOutstandingR2T", cur_pair) == 0) { 696 697 /* 698 * Save the value, but at most we'll toss out 699 * one R2T packet. 700 */ 701 c->c_max_outstanding_r2t = strtol(n, NULL, 0); 702 rval = add_text(text, text_length, cur_pair, n); 703 704 /* 705 * 12.18 -- DataPDUInOder 706 * Negotiated 707 */ 708 } else if (strcmp("DataPDUInOrder", cur_pair) == 0) { 709 710 /* 711 * We can handle DataPDU's out of order and 712 * currently we'll only send them in order. We're 713 * to far removed from the hardware to see data 714 * coming off of the platters out of order so 715 * it's unlikely we'd ever implement this feature. 716 * Store the parameter and echo back the initiators 717 * request. 718 */ 719 c->c_data_pdu_in_order = strcmp(n, "Yes") == 0 ? 720 True : False; 721 rval = add_text(text, text_length, cur_pair, n); 722 723 /* 724 * 12.19 -- DataSequenceInOrder 725 * Negotiated 726 */ 727 } else if (strcmp("DataSequenceInOrder", cur_pair) == 0) { 728 729 /* 730 * Currently we're set up to look at and require 731 * PDU sequence numbers be in order. The check 732 * now is only done as a prelude to supporting 733 * MC/S and guaranteeing the order of incoming 734 * packets on different connections. 735 */ 736 c->c_data_sequence_in_order = True; 737 rval = add_text(text, text_length, cur_pair, "Yes"); 738 739 /* 740 * 12.20 -- ErrorRecoveryLevel 741 * Negotiated 742 */ 743 } else if (strcmp("ErrorRecoveryLevel", cur_pair) == 0) { 744 745 c->c_erl = 0; 746 (void) snprintf(param_rsp, sizeof (param_rsp), 747 "%d", c->c_erl); 748 rval = add_text(text, text_length, 749 cur_pair, param_rsp); 750 751 /* 752 * 12.21 -- SessionType 753 * Declarative 754 */ 755 } else if (strcmp("SessionType", cur_pair) == 0) { 756 757 c->c_sess->s_type = strcmp(n, "Discovery") == 0 ? 758 SessionDiscovery : SessionNormal; 759 760 761 /* 762 * Appendix A 3.1 -- IFMarker 763 * Negotiated 764 */ 765 } else if (strcmp("IFMarker", cur_pair) == 0) { 766 767 c->c_ifmarker = False; 768 rval = add_text(text, text_length, cur_pair, "No"); 769 770 /* 771 * Appendix A 3.1 -- OFMarker 772 * Negotiated 773 */ 774 } else if (strcmp("OFMarker", cur_pair) == 0) { 775 776 c->c_ofmarker = False; 777 rval = add_text(text, text_length, cur_pair, "No"); 778 779 } else if ((strcmp("AuthMethod", cur_pair) == 0) || 780 (strcmp("CHAP_A", cur_pair) == 0) || 781 (strcmp("CHAP_I", cur_pair) == 0) || 782 (strcmp("CHAP_C", cur_pair) == 0) || 783 (strcmp("CHAP_N", cur_pair) == 0) || 784 (strcmp("CHAP_R", cur_pair) == 0)) { 785 786 rval = add_text(&(c->auth_text), &c->auth_text_length, 787 cur_pair, n); 788 789 } else { 790 791 /* 792 * It's perfectly legitimate for an initiator to 793 * send us a parameter we don't currently understand. 794 * For example, an initiator that supports iSER will 795 * send an RDMA options parameter. If we respond with 796 * a valid return value it knows to switch to iSER 797 * for future processing. 798 */ 799 rval = add_text(text, text_length, 800 cur_pair, "NotUnderstood"); 801 802 /* 803 * Go ahead a log this information in case we see 804 * something unexpected. 805 */ 806 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 807 "CON%x Unknown parameter %s=%s\n", 808 c->c_num, cur_pair, n); 809 } 810 811 /* 812 * If parsed both Initiator and Target names have been parsed, 813 * then it is now time to load the connection parameters. 814 * 815 * This may fail because the target doesn't exist or the 816 * initiator doesn't have permission to access this target. 817 */ 818 if ((target_name != NULL) && (initiator_name != NULL)) { 819 if ((rval = connection_parameters_get(c, target_name)) 820 == False) { 821 if ((errcode != NULL) && (*errcode == 0)) 822 *errcode = 823 (ISCSI_STATUS_CLASS_INITIATOR_ERR 824 << 8) | 825 ISCSI_LOGIN_STATUS_TGT_FORBIDDEN; 826 } else if ((rval = add_text(text, text_length, 827 "TargetAlias", c->c_targ_alias)) == True) { 828 829 /* 830 * Add TPGT now 831 */ 832 (void) snprintf(param_buf, sizeof (param_buf), 833 "%d", c->c_tpgt); 834 rval = add_text(text, text_length, 835 "TargetPortalGroupTag", param_buf); 836 target_name = initiator_name = NULL; 837 } 838 } 839 840 if (rval == False) { 841 /* 842 * Make sure the caller wants error status and that it 843 * hasn't already been set. 844 */ 845 if ((errcode != NULL) && (*errcode == 0)) 846 *errcode = 847 (ISCSI_STATUS_CLASS_TARGET_ERR << 8) | 848 ISCSI_LOGIN_STATUS_TARGET_ERROR; 849 break; 850 } 851 852 /* 853 * next pair of parameters. 1 is added to include the NULL 854 * byte and the end of each string. 855 */ 856 n = cur_pair + plen + 1; 857 dlen -= (plen + 1); 858 } 859 860 if (p != NULL) 861 free(p); 862 863 return (rval); 864 } 865 866 /* 867 * Pre-seed connection parameters to default values 868 * See RFC 3720 Section 12 869 */ 870 void 871 connection_parameters_default(iscsi_conn_t *c) 872 { 873 c->c_max_connections = 1; /* MaxConnections */ 874 c->c_tpgt = 1; /* TargetPortalGroupTag */ 875 c->c_initialR2T = True; /* InitialR2T */ 876 c->c_immediate_data = True; /* ImmediateData */ 877 c->c_max_recv_data = 8192; /* MaxRecvDataSegmentLength */ 878 c->c_max_burst_len = 262144; /* MaxBurstLength */ 879 c->c_first_burst_len = 65536; /* FirstBurstLength */ 880 c->c_default_time_2_wait = 2; /* DefaultTime2Wait */ 881 c->c_default_time_2_retain = 20; /* DefaultTime2Retain */ 882 c->c_max_outstanding_r2t = 1; /* MaxOutStandingR2T */ 883 c->c_data_pdu_in_order = True; /* DataPDUInOrder */ 884 c->c_data_sequence_in_order = True; /* DataSequenceOrder */ 885 c->c_erl = 0; /* ErrorRecoveryLevel */ 886 } 887 888 /* 889 * []---- 890 * | find_main_tpgt -- Looks up the IP address and finds a match TPGT 891 * | 892 * | If no TPGT for this address exists the routine returns 0 which 893 * | is an illegal TPGT value. 894 * []---- 895 */ 896 static int 897 find_main_tpgt(struct sockaddr_storage *pst) 898 { 899 char ip_addr[16]; 900 tgt_node_t *tpgt = NULL; 901 tgt_node_t *ip_node = NULL; 902 struct in_addr addr; 903 struct in6_addr addr6; 904 905 /* 906 * Hardly can you believe that such struct-to-struct 907 * assignment IS valid. 908 */ 909 addr = ((struct sockaddr_in *)pst)->sin_addr; 910 addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr; 911 912 while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT, 913 tpgt)) != NULL) { 914 915 ip_node = NULL; 916 while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, 917 ip_node)) != NULL) { 918 919 if (pst->ss_family == AF_INET) { 920 921 if (inet_pton(AF_INET, ip_node->x_value, 922 ip_addr) != 1) { 923 continue; 924 } 925 if (bcmp(ip_addr, &addr, 926 sizeof (struct in_addr)) == 0) { 927 return (atoi(tpgt->x_value)); 928 } 929 } else if (pst->ss_family == AF_INET6) { 930 931 if (inet_pton(AF_INET6, ip_node->x_value, 932 ip_addr) != 1) { 933 continue; 934 } 935 if (bcmp(ip_addr, &addr6, 936 sizeof (struct in6_addr)) == 0) { 937 return (atoi(tpgt->x_value)); 938 } 939 } 940 } 941 } 942 943 return (0); 944 } 945 946 /* 947 * convert_to_tpgt -- return a TPGT based on the target address 948 * 949 * If a target doesn't have a TPGT list then just return the default 950 * value of 1. Otherwise determine which TPGT the target address is 951 * part of and find that TPGT value in the list of TPGTs this target 952 * is willing to expose. If the TPGT value is not found in the list 953 * return zero which will break the connection. 954 */ 955 static int 956 convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ) 957 { 958 tgt_node_t *list; 959 tgt_node_t *tpgt = NULL; 960 int addr_tpgt, pos_tpgt; 961 962 /* 963 * If this target doesn't have a list of target portal group tags 964 * just return the default which is 1. 965 */ 966 list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL); 967 if (list == NULL) 968 return (1); 969 970 /* 971 * If we don't find our IP in the general configuration list 972 * we'll use the default value which is 1 according to RFC3720. 973 */ 974 addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr)); 975 976 while ((tpgt = tgt_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) { 977 (void) tgt_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt); 978 if (pos_tpgt == addr_tpgt) { 979 return (addr_tpgt); 980 } 981 } 982 983 return (0); 984 } 985 986 /* 987 * []---- 988 * | find_target_node -- given a target IQN name, return the XML node 989 * []---- 990 */ 991 tgt_node_t * 992 find_target_node(char *targ_name) 993 { 994 tgt_node_t *tnode = NULL; 995 char *iname; 996 997 while ((tnode = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 998 tnode)) != NULL) { 999 if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) == 1000 True) { 1001 if (strcmp(iname, targ_name) == 0) { 1002 free(iname); 1003 return (tnode); 1004 } else 1005 free(iname); 1006 } 1007 } 1008 1009 return (NULL); 1010 } 1011 1012 static Boolean_t 1013 connection_parameters_get(iscsi_conn_t *c, char *targ_name) 1014 { 1015 tgt_node_t *targ, *alias; 1016 Boolean_t rval = False; 1017 1018 (void) pthread_rwlock_rdlock(&targ_config_mutex); 1019 if ((targ = find_target_node(targ_name)) != NULL) { 1020 1021 if (check_access(targ, c->c_sess->s_i_name, False) == False) { 1022 (void) pthread_rwlock_unlock(&targ_config_mutex); 1023 return (False); 1024 } 1025 1026 /* 1027 * Have a valid node for our target. Start looking 1028 * for connection oriented parameters. 1029 */ 1030 if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0) { 1031 (void) pthread_rwlock_unlock(&targ_config_mutex); 1032 return (False); 1033 } 1034 if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) == 1035 NULL) { 1036 (void) tgt_find_value_str(targ, XML_ELEMENT_TARG, 1037 &c->c_targ_alias); 1038 } else { 1039 (void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS, 1040 &c->c_targ_alias); 1041 } 1042 1043 (void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS, 1044 &c->c_maxcmdsn); 1045 rval = True; 1046 } 1047 1048 (void) pthread_rwlock_unlock(&targ_config_mutex); 1049 return (rval); 1050 } 1051 1052 Boolean_t 1053 validate_version(tgt_node_t *node, int *maj_p, int *min_p) 1054 { 1055 char *vers_str = NULL; 1056 char *minor_part; 1057 int maj, min; 1058 1059 if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) || 1060 (vers_str == NULL)) 1061 return (False); 1062 1063 maj = strtol(vers_str, &minor_part, 0); 1064 if ((maj > *maj_p) || (minor_part == NULL) || (*minor_part != '.')) { 1065 free(vers_str); 1066 return (False); 1067 } 1068 1069 min = strtol(&minor_part[1], NULL, 0); 1070 *maj_p = maj; 1071 *min_p = min; 1072 free(vers_str); 1073 1074 return (True); 1075 } 1076 1077 /* 1078 * []---- 1079 * | sna_lt -- Serial Number Arithmetic, 32 bits, less than, RFC1982 1080 * []---- 1081 */ 1082 int 1083 sna_lt(uint32_t n1, uint32_t n2) 1084 { 1085 return ((n1 != n2) && 1086 (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || 1087 ((n1 > n2) && ((n1 - n2) > SNA32_CHECK)))); 1088 } 1089 1090 /* 1091 * []---- 1092 * sna_lte -- Serial Number Arithmetic, 32 bits, less than, RFC1982 1093 * []---- 1094 */ 1095 int 1096 sna_lte(uint32_t n1, uint32_t n2) 1097 { 1098 return ((n1 == n2) || 1099 (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || 1100 ((n1 > n2) && ((n1 - n2) > SNA32_CHECK)))); 1101 } 1102 1103 /* 1104 * util_create_guid -- generate GUID based on the guid type 1105 * id_type: SPC_INQUIRY_ID_TYPE_EUI - 1106 * EUI-64 based 16-byte designator format; 1107 * SPC_INQUIRY_ID_TYPE_NAA - 1108 * NAA IEEE Registered Extended designator format. 1109 * 1110 * SPC-4 revision 11 section 7.6.3.5.4 and 7.6.3.6.5. 1111 * 1112 * Note that now this function is always called with parameter 1113 * id_type SPC_INQUIRY_ID_TYPE_NAA, therefore the code for creating 1114 * EUI-64 based 16-byte format GUID is no longer used. But in order 1115 * to keep backward compatiability and for future extension, all the 1116 * code that has been used for creating old GUIDs should be kept, to 1117 * make the format clear for all possible GUIDs targets might have. 1118 */ 1119 Boolean_t 1120 util_create_guid(char **guid, uchar_t id_type) 1121 { 1122 eui_16_t eui; 1123 /* 1124 * We only have room for 32bits of data in the GUID. The hiword/loword 1125 * macros will not work on 64bit variables. The work, but produce 1126 * invalid results on Big Endian based machines. 1127 */ 1128 uint32_t tval = (uint_t)time((time_t *)0); 1129 size_t guid_size; 1130 int i, fd; 1131 1132 /* 1133 * Create the NAA (6) GUID. 1134 */ 1135 if (id_type == SPC_INQUIRY_ID_TYPE_NAA) { 1136 return (util_create_guid_naa(guid)); 1137 } 1138 1139 if ((mac_len == 0) && (if_find_mac(NULL) == False)) { 1140 1141 /* 1142 * By default strict GUID generation is enforced. This can 1143 * be disabled by using the correct XML tag in the configuration 1144 * file. 1145 */ 1146 if (enforce_strict_guid == True) 1147 return (False); 1148 1149 /* 1150 * There's no MAC address available and we've even tried 1151 * a second time to get one. So fallback to using a random 1152 * number for the MAC address. 1153 */ 1154 if ((fd = open("/dev/random", O_RDONLY)) < 0) 1155 return (False); 1156 if (read(fd, &eui, sizeof (eui)) != sizeof (eui)) 1157 return (False); 1158 (void) close(fd); 1159 1160 eui.e_vers = SUN_EUI_16_VERS; 1161 eui.e_company_id[0] = (SUN_EN >> 16) & 0xff; 1162 eui.e_company_id[1] = (SUN_EN >> 8) & 0xff; 1163 eui.e_company_id[2] = SUN_EN & 0xff; 1164 1165 } else { 1166 bzero(&eui, sizeof (eui)); 1167 1168 eui.e_vers = SUN_EUI_16_VERS; 1169 eui.e_company_id[0] = (SUN_EN >> 16) & 0xff; 1170 eui.e_company_id[1] = (SUN_EN >> 8) & 0xff; 1171 eui.e_company_id[2] = SUN_EN & 0xff; 1172 eui.e_timestamp[0] = hibyte(hiword(tval)); 1173 eui.e_timestamp[1] = lobyte(hiword(tval)); 1174 eui.e_timestamp[2] = hibyte(loword(tval)); 1175 eui.e_timestamp[3] = lobyte(loword(tval)); 1176 for (i = 0; i < min(mac_len, sizeof (eui.e_mac)); i++) { 1177 eui.e_mac[i] = mac_addr[i]; 1178 } 1179 1180 /* 1181 * To prevent duplicate GUIDs we need to sleep for one 1182 * second here since part of the GUID is a time stamp with 1183 * a one second resolution. 1184 */ 1185 (void) sleep(1); 1186 } 1187 1188 if (tgt_xml_encode((uint8_t *)&eui, sizeof (eui), guid, 1189 &guid_size) == False) { 1190 return (False); 1191 } else 1192 return (True); 1193 } 1194 1195 Boolean_t 1196 util_create_guid_naa(char **guid) 1197 { 1198 naa_16_t naa; 1199 /* 1200 * We only have room for 32bits of data in the GUID. The hiword/loword 1201 * macros will not work on 64bit variables. The work, but produce 1202 * invalid results on Big Endian based machines. 1203 */ 1204 uint32_t tval = (uint_t)time((time_t *)0); 1205 size_t guid_size; 1206 int i, fd; 1207 1208 if ((mac_len == 0) && (if_find_mac(NULL) == False)) { 1209 1210 /* 1211 * By default strict GUID generation is enforced. This can 1212 * be disabled by using the correct XML tag in the configuration 1213 * file. 1214 */ 1215 if (enforce_strict_guid == True) 1216 return (False); 1217 1218 /* 1219 * There's no MAC address available and we've even tried 1220 * a second time to get one. So fallback to using a random 1221 * number for the MAC address. 1222 */ 1223 if ((fd = open("/dev/random", O_RDONLY)) < 0) 1224 return (False); 1225 if (read(fd, &naa, sizeof (naa)) != sizeof (naa)) 1226 return (False); 1227 (void) close(fd); 1228 1229 } else { 1230 bzero(&naa, sizeof (naa)); 1231 1232 /* 1233 * Set vendor specific identifier and extension. 1234 */ 1235 naa.n_timestamp[0] = hibyte(hiword(tval)); 1236 naa.n_timestamp[1] = lobyte(hiword(tval)); 1237 naa.n_timestamp[2] = hibyte(loword(tval)); 1238 naa.n_timestamp[3] = lobyte(loword(tval)); 1239 for (i = 0; i < min(mac_len, sizeof (naa.n_mac)); i++) { 1240 naa.n_mac[i] = mac_addr[i]; 1241 } 1242 1243 /* 1244 * To prevent duplicate GUIDs we need to sleep for one 1245 * second here since part of the GUID is a time stamp with 1246 * a one second resolution. 1247 */ 1248 (void) sleep(1); 1249 } 1250 1251 /* 1252 * Set NAA (6) and IEEE Company_ID. 1253 */ 1254 naa.n_naa = SUN_NAA_16_TYPE; 1255 naa.n_company_id_hi = (SUN_EN >> 20) & 0x0f; 1256 naa.n_company_id_b1 = (SUN_EN >> 12) & 0xff; 1257 naa.n_company_id_b2 = (SUN_EN >> 4) & 0xff; 1258 naa.n_company_id_lo = SUN_EN & 0x0f; 1259 if (tgt_xml_encode((uint8_t *)&naa, sizeof (naa), guid, 1260 &guid_size) == False) { 1261 return (False); 1262 } else 1263 return (True); 1264 } 1265 1266 /* 1267 * []---- 1268 * | create_geom -- based on size, determine best fit for CHS 1269 * | 1270 * | Given size in bytes, which will be adjusted to blocks, find 1271 * | the best fit for making (C * H * S == blocks) 1272 * | 1273 * | Note that the following algorithm was derived from the 1274 * | common disk label implementation, cmlb_convert_geometry(). 1275 * | 1276 * []---- 1277 */ 1278 void 1279 create_geom(diskaddr_t size, int *cylinders, int *heads, int *spt) 1280 { 1281 diskaddr_t blocks = size >> 9; /* 512 bytes/block */ 1282 1283 /* 1284 * For all devices we calculate cylinders using the heads and sectors 1285 * we assign based on capacity of the device. The algorithm is 1286 * designed to be compatible with the way other operating systems 1287 * lay out fdisk tables for X86 and to insure that the cylinders never 1288 * exceed 65535 to prevent problems with X86 ioctls that report 1289 * geometry. 1290 * For some smaller disk sizes we report geometry that matches those 1291 * used by X86 BIOS usage. For larger disks, we use SPT that are 1292 * multiples of 63, since other OSes that are not limited to 16-bits 1293 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT. 1294 * 1295 * The following table (in order) illustrates some end result 1296 * calculations: 1297 * 1298 * Maximum number of blocks nhead nsect 1299 * 1300 * 2097152 (1GB) 64 32 1301 * 16777216 (8GB) 128 32 1302 * 1052819775 (502.02GB) 255 63 1303 * 2105639550 (0.98TB) 255 126 1304 * 3158459325 (1.47TB) 255 189 1305 * 4211279100 (1.96TB) 255 252 1306 * 5264098875 (2.45TB) 255 315 1307 * ... 1308 */ 1309 1310 if (blocks <= 0x200000) { 1311 *heads = 64; 1312 *spt = 32; 1313 } else if (blocks <= 0x01000000) { 1314 *heads = 128; 1315 *spt = 32; 1316 } else { 1317 *heads = 255; 1318 1319 /* make sectors-per-track be smallest multiple of 63 */ 1320 *spt = ((blocks + 1321 (UINT16_MAX * 255 * 63) - 1) / 1322 (UINT16_MAX * 255 * 63)) * 63; 1323 1324 if (*spt == 0) 1325 *spt = (UINT16_MAX / 63) * 63; 1326 } 1327 1328 /* cyls/dsk = (sectors/dsk) / (sectors/trk * tracks/cyl) */ 1329 *cylinders = blocks / (*spt * *heads); 1330 } 1331 1332 /* 1333 * []---- 1334 * | strtol_multiplier -- common method to deal with human type numbers 1335 * []---- 1336 */ 1337 Boolean_t 1338 strtoll_multiplier(char *str, uint64_t *sp) 1339 { 1340 char *m; 1341 uint64_t size; 1342 1343 size = strtoll(str, &m, 0); 1344 if (m && *m) { 1345 switch (*m) { 1346 case 't': 1347 case 'T': 1348 size *= 1024; 1349 /*FALLTHRU*/ 1350 case 'g': 1351 case 'G': 1352 size *= 1024; 1353 /*FALLTHRU*/ 1354 case 'm': 1355 case 'M': 1356 size *= 1024; 1357 /*FALLTHRU*/ 1358 case 'k': 1359 case 'K': 1360 size *= 1024; 1361 break; 1362 1363 default: 1364 return (False); 1365 } 1366 } 1367 1368 *sp = size; 1369 return (True); 1370 } 1371 1372 /* 1373 * []---- 1374 * | util_title -- print out start/end title in consistent manner 1375 * []---- 1376 */ 1377 void 1378 util_title(target_queue_t *q, int type, int num, char *title) 1379 { 1380 char *type_str; 1381 int len, pad; 1382 1383 len = strlen(title); 1384 pad = len & 1; 1385 1386 switch (type) { 1387 case Q_CONN_LOGIN: 1388 case Q_CONN_NONIO: 1389 type_str = "CON"; 1390 break; 1391 1392 case Q_SESS_LOGIN: 1393 case Q_SESS_NONIO: 1394 type_str = "SES"; 1395 break; 1396 1397 case Q_STE_NONIO: 1398 type_str = "SAM"; 1399 break; 1400 1401 default: 1402 type_str = "UGH"; 1403 break; 1404 } 1405 1406 queue_prt(q, type, "%s%x ---- %*s%s%*s ----\n", type_str, num, 1407 ((60 - len) / 2), "", title, ((60 - len) / 2) + pad, ""); 1408 } 1409 1410 /* 1411 * []---- 1412 * | task_to_str -- convert task management event to string (DEBUG USE) 1413 * []---- 1414 */ 1415 char * 1416 task_to_str(int func) 1417 { 1418 switch (func) { 1419 case ISCSI_TM_FUNC_ABORT_TASK: return ("Abort"); 1420 case ISCSI_TM_FUNC_ABORT_TASK_SET: return ("Abort Set"); 1421 case ISCSI_TM_FUNC_CLEAR_ACA: return ("Clear ACA"); 1422 case ISCSI_TM_FUNC_CLEAR_TASK_SET: return ("Clear Task"); 1423 case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: return ("LUN Reset"); 1424 case ISCSI_TM_FUNC_TARGET_WARM_RESET: return ("Target Warm Reset"); 1425 case ISCSI_TM_FUNC_TARGET_COLD_RESET: return ("Target Cold Reset"); 1426 case ISCSI_TM_FUNC_TASK_REASSIGN: return ("Task Reassign"); 1427 default: return ("Unknown"); 1428 } 1429 } 1430 1431 /* 1432 * []---- 1433 * | xml_rtn_msg -- create a common format for XML replies to management UI 1434 * []---- 1435 */ 1436 void 1437 xml_rtn_msg(char **buf, err_code_t code) 1438 { 1439 char lbuf[16]; 1440 1441 tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'"); 1442 (void) snprintf(lbuf, sizeof (lbuf), "%d", code); 1443 tgt_buf_add(buf, XML_ELEMENT_CODE, lbuf); 1444 tgt_buf_add(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code)); 1445 tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End); 1446 } 1447 1448 /* 1449 * []---- 1450 * | thick_provo_start -- start an initialization thread for targ/lun 1451 * []---- 1452 */ 1453 void * 1454 thick_provo_start(void *v) 1455 { 1456 thick_provo_t *tp = (thick_provo_t *)v; 1457 msg_t *m; 1458 Boolean_t rval; 1459 char *err = NULL; 1460 1461 /* 1462 * Add this threads information to the main queue. This is 1463 * used in case the administrator decides to remove the LU 1464 * before the initialization is complete. 1465 */ 1466 (void) pthread_mutex_lock(&thick_mutex); 1467 if (thick_head == NULL) { 1468 thick_head = tp; 1469 } else { 1470 thick_tail->next = tp; 1471 tp->prev = thick_tail; 1472 } 1473 thick_tail = tp; 1474 (void) pthread_mutex_unlock(&thick_mutex); 1475 1476 /* 1477 * This let's the parent thread know this thread is running. 1478 */ 1479 queue_message_set(tp->q, 0, msg_mgmt_rply, 0); 1480 1481 /* ---- Start the initialization of the LU ---- */ 1482 rval = t10_thick_provision(tp->targ_name, tp->lun, tp->q); 1483 1484 /* ---- Remove from the linked list ---- */ 1485 (void) pthread_mutex_lock(&thick_mutex); 1486 if (tp->prev == NULL) { 1487 assert(tp == thick_head); 1488 thick_head = tp->next; 1489 if (tp->next == NULL) { 1490 assert(tp == thick_tail); 1491 thick_tail = NULL; 1492 } else 1493 tp->next->prev = NULL; 1494 } else { 1495 tp->prev->next = tp->next; 1496 if (tp->next != NULL) 1497 tp->next->prev = tp->prev; 1498 else 1499 thick_tail = tp->prev; 1500 } 1501 (void) pthread_mutex_unlock(&thick_mutex); 1502 1503 /* 1504 * There's a race condition where t10_thick_provision() could 1505 * finish and before the thick_mutex lock is grabbed again 1506 * that another thread running the thick_provo_stop() could 1507 * find a match and send a shutdown message. If that happened 1508 * that thread would wait forever in queue_message_get(). So, 1509 * After this target/lun pair has been removed check the message 1510 * queue one last time to see if there's a message available. 1511 * If so, send an ack. 1512 */ 1513 m = queue_message_try_get(tp->q); 1514 if (m != NULL) { 1515 assert(m->msg_type == msg_shutdown); 1516 queue_message_set((target_queue_t *)m->msg_data, 0, 1517 msg_shutdown_rsp, 0); 1518 } 1519 1520 if (rval == True) 1521 iscsi_inventory_change(tp->targ_name); 1522 else { 1523 queue_prt(mgmtq, Q_GEN_ERRS, "Failed to initialize %s/%d\n", 1524 tp->targ_name, tp->lun); 1525 syslog(LOG_ERR, "Failed to initialize %s, LU%d", tp->targ_name, 1526 tp->lun); 1527 remove_target_common(tp->targ_name, tp->lun, &err); 1528 if (err != NULL) { 1529 1530 /* 1531 * There's not much we can do here. The most likely 1532 * cause of not being able to remove the target is 1533 * that it's LU 0 and there is currently another 1534 * LU allocated. 1535 */ 1536 queue_prt(mgmtq, Q_GEN_ERRS, 1537 "Failed to remove target\n"); 1538 syslog(LOG_ERR, "Failed to remove target/lun after " 1539 "initialization failure"); 1540 } 1541 } 1542 1543 free(tp->targ_name); 1544 queue_free(tp->q, NULL); 1545 free(tp); 1546 1547 queue_message_set(mgmtq, 0, msg_pthread_join, 1548 (void *)(uintptr_t)pthread_self()); 1549 return (NULL); 1550 } 1551 1552 /* 1553 * []---- 1554 * | thick_provo_stop -- stop initialization thread for given targ/lun 1555 * []---- 1556 */ 1557 void 1558 thick_provo_stop(char *targ, int lun) 1559 { 1560 thick_provo_t *tp; 1561 target_queue_t *q = queue_alloc(); 1562 1563 (void) pthread_mutex_lock(&thick_mutex); 1564 tp = thick_head; 1565 while (tp) { 1566 if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) { 1567 queue_message_set(tp->q, 0, msg_shutdown, (void *)q); 1568 /* 1569 * Drop the global mutex because it's entirely 1570 * possible for a thick_provo_start thread to be 1571 * in the early stages in which it will can call 1572 * thick_provo_chk() from the T10 SAM code. 1573 */ 1574 (void) pthread_mutex_unlock(&thick_mutex); 1575 1576 queue_message_free(queue_message_get(q)); 1577 1578 /* 1579 * Pick the lock back up since it'll make the 1580 * finish stage easier to deal with. 1581 */ 1582 (void) pthread_mutex_lock(&thick_mutex); 1583 break; 1584 } 1585 tp = tp->next; 1586 } 1587 (void) pthread_mutex_unlock(&thick_mutex); 1588 queue_free(q, NULL); 1589 } 1590 1591 /* 1592 * []---- 1593 * | thick_provo_chk_thr -- see if there's an initialization thread running 1594 * []---- 1595 */ 1596 Boolean_t 1597 thick_provo_chk_thr(char *targ, int lun) 1598 { 1599 thick_provo_t *tp; 1600 Boolean_t rval = False; 1601 1602 (void) pthread_mutex_lock(&thick_mutex); 1603 tp = thick_head; 1604 while (tp) { 1605 if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) { 1606 rval = True; 1607 break; 1608 } 1609 tp = tp->next; 1610 } 1611 (void) pthread_mutex_unlock(&thick_mutex); 1612 1613 return (rval); 1614 } 1615 1616 /* 1617 * []---- 1618 * | remove_target_common -- remove targ/lun from system. 1619 * | 1620 * | This is a common function that's used both by the normal remove 1621 * | target code and when a write failure occurs during initialization. 1622 * | It will handle being given either the local target name or the full 1623 * | IQN name of the target. 1624 * []---- 1625 */ 1626 void 1627 remove_target_common(char *name, int lun_num, char **msg) 1628 { 1629 tgt_node_t *targ = NULL; 1630 tgt_node_t *list, *lun, *c; 1631 char path[MAXPATHLEN]; 1632 char *tname = NULL; 1633 char *iname = NULL; 1634 int chk; 1635 1636 while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 1637 targ)) != NULL) { 1638 /* ---- Look for a match on the friendly name ---- */ 1639 if (strcmp(targ->x_value, name) == 0) { 1640 tname = name; 1641 break; 1642 } 1643 1644 /* ---- Check to see if they gave the IQN name instead ---- */ 1645 if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) == 1646 True) && (strcmp(iname, name) == 0)) 1647 break; 1648 else { 1649 free(iname); 1650 iname = NULL; 1651 } 1652 } 1653 1654 /* ---- Check to see if it's already been removed ---- */ 1655 if (targ == NULL) { 1656 return; 1657 } 1658 1659 /* 1660 * We need both the friendly and IQN names so figure out which wasn't 1661 * given and find it's value. 1662 */ 1663 if (tname == NULL) 1664 tname = targ->x_value; 1665 if (iname == NULL) { 1666 if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) == 1667 False) { 1668 xml_rtn_msg(msg, ERR_INTERNAL_ERROR); 1669 return; 1670 } 1671 } 1672 1673 if ((list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) 1674 goto error; 1675 1676 if (lun_num == 0) { 1677 1678 /* 1679 * LUN must be the last one removed, so check to 1680 * see if others are still present. 1681 */ 1682 lun = NULL; 1683 while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) != 1684 NULL) { 1685 if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) == 1686 False) 1687 goto error; 1688 1689 if (chk != lun_num) { 1690 xml_rtn_msg(msg, ERR_LUN_ZERO_NOT_LAST); 1691 goto error; 1692 } 1693 } 1694 } else { 1695 1696 /* 1697 * Make sure the LU exists that's being removed 1698 */ 1699 lun = NULL; 1700 while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) != 1701 NULL) { 1702 if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) == 1703 False) 1704 goto error; 1705 1706 if (chk == lun_num) { 1707 lun = tgt_node_alloc(XML_ELEMENT_LUN, Int, 1708 &lun_num); 1709 (void) tgt_node_remove(list, lun, MatchBoth); 1710 tgt_node_free(lun); 1711 break; 1712 } 1713 } 1714 if (lun == NULL) { 1715 xml_rtn_msg(msg, ERR_LUN_NOT_FOUND); 1716 goto error; 1717 } 1718 } 1719 1720 /* ---- Say goodbye to that data ---- */ 1721 (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir, 1722 iname, LUNBASE, lun_num); 1723 (void) unlink(path); 1724 (void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir, 1725 iname, PARAMBASE, lun_num); 1726 (void) unlink(path); 1727 1728 (void) mgmt_param_remove(tname, lun_num); 1729 1730 /* 1731 * If the was LUN 0 then do to the previous check 1732 * we know that no other files exist in the target 1733 * directory so the target information can be removed 1734 * along with the directory. 1735 */ 1736 if (lun_num == 0) { 1737 (void) snprintf(path, sizeof (path), "%s/%s", target_basedir, 1738 iname); 1739 (void) rmdir(path); 1740 1741 /* 1742 * Don't forget to remove the symlink to 1743 * the target directory. 1744 */ 1745 (void) snprintf(path, sizeof (path), "%s/%s", target_basedir, 1746 tname); 1747 (void) unlink(path); 1748 1749 /* 1750 * 'tname' is just a reference to the memory within 1751 * the targets_config structure. So once the tgt_node_remove() 1752 * is called 'tname' is no longer valid. 1753 */ 1754 c = tgt_node_alloc(XML_ELEMENT_TARG, String, tname); 1755 (void) tgt_node_remove(targets_config, c, MatchBoth); 1756 tgt_node_free(c); 1757 } 1758 1759 /* 1760 * Not much we can do here if we fail to updated the config. 1761 */ 1762 if (mgmt_config_save2scf() == False) 1763 syslog(LOG_ERR, "Failed to update target configuration!"); 1764 1765 error: 1766 if (iname != NULL) 1767 free(iname); 1768 } 1769 1770 /* 1771 * []---- 1772 * | validate_xml 1773 * | 1774 * | This function checks if there is predefined entities &<>'" in xml request 1775 * []---- 1776 */ 1777 Boolean_t 1778 validate_xml(char *req) 1779 { 1780 in_mark_t in_mark = in_none; 1781 1782 if (req == NULL) 1783 return (False); 1784 for (; *req != '\0'; req++) { 1785 if (in_mark == in_none) { 1786 if (*req == '<') { 1787 in_mark = in_lt; 1788 continue; 1789 } else if (*req == '&') { 1790 in_mark = in_amp; 1791 continue; 1792 } else if (strchr("\"\'>", *req) != NULL) { 1793 return (False); 1794 } 1795 } else if (in_mark == in_lt) { 1796 if (*req == '>') { 1797 in_mark = in_none; 1798 continue; 1799 } else if (*req == '<') { 1800 return (False); 1801 } 1802 } else { 1803 if (*req == ';') { 1804 in_mark = in_none; 1805 continue; 1806 } else if (*req == '&' || *req == '<') { 1807 return (False); 1808 } 1809 } 1810 } 1811 1812 if (in_mark == in_none) 1813 return (True); 1814 else 1815 return (False); 1816 } 1817 1818 /* 1819 * []---- 1820 * | get_local_name 1821 * | 1822 * | This function fetches local name from a iscsi-name 1823 * | Caller is responsible to free the string. 1824 * []---- 1825 */ 1826 char * 1827 get_local_name(char *iname) 1828 { 1829 tgt_node_t *targ = NULL; 1830 char *str; 1831 char *ret = NULL; 1832 1833 while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 1834 targ)) != NULL) { 1835 if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) == True) { 1836 if (strcmp(str, iname) == 0) 1837 ret = strdup(targ->x_value); 1838 free(str); 1839 if (ret != NULL) 1840 break; 1841 } 1842 } 1843 return (ret); 1844 } 1845