1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "spdk/stdinc.h" 36 37 #include "spdk/env.h" 38 #include "spdk/event.h" 39 #include "spdk/conf.h" 40 #include "spdk/net.h" 41 42 #include "spdk_internal/log.h" 43 44 #include "iscsi/iscsi.h" 45 #include "iscsi/conn.h" 46 #include "iscsi/tgt_node.h" 47 #include "iscsi/portal_grp.h" 48 #include "iscsi/init_grp.h" 49 #include "spdk/scsi.h" 50 #include "iscsi/task.h" 51 52 #define MAX_TMPBUF 1024 53 #define MAX_MASKBUF 128 54 55 static int 56 spdk_iscsi_tgt_node_allow_ipv6(const char *netmask, const char *addr) 57 { 58 struct in6_addr in6_mask; 59 struct in6_addr in6_addr; 60 char mask[MAX_MASKBUF]; 61 const char *p; 62 size_t n; 63 int bits, bmask; 64 int i; 65 66 if (netmask[0] != '[') 67 return 0; 68 p = strchr(netmask, ']'); 69 if (p == NULL) 70 return 0; 71 n = p - (netmask + 1); 72 if (n + 1 > sizeof mask) 73 return 0; 74 75 memcpy(mask, netmask + 1, n); 76 mask[n] = '\0'; 77 p++; 78 79 if (p[0] == '/') { 80 bits = (int) strtol(p + 1, NULL, 10); 81 if (bits < 0 || bits > 128) 82 return 0; 83 } else { 84 bits = 128; 85 } 86 87 #if 0 88 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "input %s\n", addr); 89 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "mask %s / %d\n", mask, bits); 90 #endif 91 92 /* presentation to network order binary */ 93 if (inet_pton(AF_INET6, mask, &in6_mask) <= 0 94 || inet_pton(AF_INET6, addr, &in6_addr) <= 0) { 95 return 0; 96 } 97 98 /* check 128bits */ 99 for (i = 0; i < (bits / 8); i++) { 100 if (in6_mask.s6_addr[i] != in6_addr.s6_addr[i]) 101 return 0; 102 } 103 if (bits % 8) { 104 bmask = (0xffU << (8 - (bits % 8))) & 0xffU; 105 if ((in6_mask.s6_addr[i] & bmask) != (in6_addr.s6_addr[i] & bmask)) 106 return 0; 107 } 108 109 /* match */ 110 return 1; 111 } 112 113 static int 114 spdk_iscsi_tgt_node_allow_ipv4(const char *netmask, const char *addr) 115 { 116 struct in_addr in4_mask; 117 struct in_addr in4_addr; 118 char mask[MAX_MASKBUF]; 119 const char *p; 120 uint32_t bmask; 121 size_t n; 122 int bits; 123 124 p = strchr(netmask, '/'); 125 if (p == NULL) { 126 p = netmask + strlen(netmask); 127 } 128 n = p - netmask; 129 if (n + 1 > sizeof mask) 130 return 0; 131 132 memcpy(mask, netmask, n); 133 mask[n] = '\0'; 134 135 if (p[0] == '/') { 136 bits = (int) strtol(p + 1, NULL, 10); 137 if (bits < 0 || bits > 32) 138 return 0; 139 } else { 140 bits = 32; 141 } 142 143 /* presentation to network order binary */ 144 if (inet_pton(AF_INET, mask, &in4_mask) <= 0 145 || inet_pton(AF_INET, addr, &in4_addr) <= 0) { 146 return 0; 147 } 148 149 /* check 32bits */ 150 bmask = (0xffffffffULL << (32 - bits)) & 0xffffffffU; 151 if ((ntohl(in4_mask.s_addr) & bmask) != (ntohl(in4_addr.s_addr) & bmask)) 152 return 0; 153 154 /* match */ 155 return 1; 156 } 157 158 static int 159 spdk_iscsi_tgt_node_allow_netmask(const char *netmask, const char *addr) 160 { 161 if (netmask == NULL || addr == NULL) 162 return 0; 163 if (strcasecmp(netmask, "ALL") == 0) 164 return 1; 165 if (netmask[0] == '[') { 166 /* IPv6 */ 167 if (spdk_iscsi_tgt_node_allow_ipv6(netmask, addr)) 168 return 1; 169 } else { 170 /* IPv4 */ 171 if (spdk_iscsi_tgt_node_allow_ipv4(netmask, addr)) 172 return 1; 173 } 174 return 0; 175 } 176 177 int 178 spdk_iscsi_tgt_node_access(struct spdk_iscsi_conn *conn, 179 struct spdk_iscsi_tgt_node *target, const char *iqn, const char *addr) 180 { 181 struct spdk_iscsi_portal_grp *pg; 182 struct spdk_iscsi_init_grp *igp; 183 int rc; 184 int i, j, k; 185 186 if (conn == NULL || target == NULL || iqn == NULL || addr == NULL) 187 return 0; 188 pg = conn->portal->group; 189 190 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "pg=%d, iqn=%s, addr=%s\n", 191 pg->tag, iqn, addr); 192 for (i = 0; i < target->maxmap; i++) { 193 /* skip excluding self portal group tag */ 194 if (pg != target->map[i].pg) 195 continue; 196 /* iqn is initiator group? */ 197 igp = target->map[i].ig; 198 for (j = 0; j < igp->ninitiators; j++) { 199 /* deny initiators */ 200 if (igp->initiators[j][0] == '!' 201 && (strcasecmp(&igp->initiators[j][1], "ALL") == 0 202 || strcasecmp(&igp->initiators[j][1], iqn) == 0)) { 203 /* NG */ 204 SPDK_TRACELOG(SPDK_TRACE_ISCSI, 205 "access denied from %s (%s) to %s (%s:%s,%d)\n", 206 iqn, addr, target->name, conn->portal->host, 207 conn->portal->port, conn->portal->group->tag); 208 return 0; 209 } 210 /* allow initiators */ 211 if (strcasecmp(igp->initiators[j], "ALL") == 0 212 || strcasecmp(igp->initiators[j], iqn) == 0) { 213 /* OK iqn, check netmask */ 214 if (igp->nnetmasks == 0) { 215 /* OK, empty netmask as ALL */ 216 return 1; 217 } 218 for (k = 0; k < igp->nnetmasks; k++) { 219 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 220 "netmask=%s, addr=%s\n", 221 igp->netmasks[k], addr); 222 rc = spdk_iscsi_tgt_node_allow_netmask(igp->netmasks[k], addr); 223 if (rc > 0) { 224 /* OK netmask */ 225 return 1; 226 } 227 } 228 /* NG netmask in this group */ 229 } 230 } 231 } 232 233 /* NG */ 234 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "access denied from %s (%s) to %s (%s:%s,%d)\n", 235 iqn, addr, target->name, conn->portal->host, 236 conn->portal->port, conn->portal->group->tag); 237 return 0; 238 } 239 240 static int 241 spdk_iscsi_tgt_node_visible(struct spdk_iscsi_tgt_node *target, const char *iqn, int pg_tag) 242 { 243 struct spdk_iscsi_init_grp *igp; 244 int match_pg_tag; 245 int i, j; 246 247 if (target == NULL || iqn == NULL) 248 return 0; 249 /* pg_tag exist map? */ 250 match_pg_tag = 0; 251 for (i = 0; i < target->maxmap; i++) { 252 if (target->map[i].pg->tag == pg_tag) { 253 match_pg_tag = 1; 254 break; 255 } 256 } 257 if (match_pg_tag == 0) { 258 /* cat't access from pg_tag */ 259 return 0; 260 } 261 for (i = 0; i < target->maxmap; i++) { 262 /* iqn is initiator group? */ 263 igp = target->map[i].ig; 264 for (j = 0; j < igp->ninitiators; j++) { 265 if (igp->initiators[j][0] == '!' 266 && (strcasecmp(&igp->initiators[j][1], "ALL") == 0 267 || strcasecmp(&igp->initiators[j][1], iqn) == 0)) { 268 /* NG */ 269 return 0; 270 } 271 if (strcasecmp(igp->initiators[j], "ALL") == 0 272 || strcasecmp(igp->initiators[j], iqn) == 0) { 273 /* OK iqn, no check addr */ 274 return 1; 275 } 276 } 277 } 278 279 /* NG */ 280 return 0; 281 } 282 283 static int 284 spdk_iscsi_portal_grp_is_visible(struct spdk_iscsi_tgt_node *target, 285 const char *iqn, int pg_tag) 286 { 287 struct spdk_iscsi_init_grp *igp; 288 int match_idx; 289 int i, j; 290 291 if (target == NULL || iqn == NULL) 292 return 0; 293 match_idx = -1; 294 for (i = 0; i < target->maxmap; i++) { 295 if (target->map[i].pg->tag == pg_tag) { 296 match_idx = i; 297 break; 298 } 299 } 300 if (match_idx < 0) { 301 /* cant't find pg_tag */ 302 return 0; 303 } 304 305 /* iqn is initiator group? */ 306 igp = target->map[match_idx].ig; 307 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "iqn=%s, pg=%d, ig=%d\n", iqn, pg_tag, igp->tag); 308 309 for (j = 0; j < igp->ninitiators; j++) { 310 if (igp->initiators[j][0] == '!' 311 && (strcasecmp(&igp->initiators[j][1], "ALL") == 0 312 || strcasecmp(&igp->initiators[j][1], iqn) == 0)) { 313 /* NG */ 314 return 0; 315 } 316 if (strcasecmp(igp->initiators[j], "ALL") == 0 317 || strcasecmp(igp->initiators[j], iqn) == 0) { 318 /* OK iqn, no check addr */ 319 return 1; 320 } 321 } 322 323 /* NG */ 324 return 0; 325 } 326 327 int 328 spdk_iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn, 329 const char *iaddr, const char *tiqn, uint8_t *data, int alloc_len, 330 int data_len) 331 { 332 char buf[MAX_TMPBUF]; 333 struct spdk_iscsi_portal_grp *pg; 334 struct spdk_iscsi_portal *p; 335 struct spdk_iscsi_tgt_node *target; 336 char *host; 337 int total; 338 int len; 339 int rc; 340 int pg_tag; 341 int i, j, k; 342 343 if (conn == NULL) 344 return 0; 345 346 total = data_len; 347 if (alloc_len < 1) { 348 return 0; 349 } 350 if (total > alloc_len) { 351 total = alloc_len; 352 data[total - 1] = '\0'; 353 return total; 354 } 355 356 if (alloc_len - total < 1) { 357 SPDK_ERRLOG("data space small %d\n", alloc_len); 358 return total; 359 } 360 361 pthread_mutex_lock(&g_spdk_iscsi.mutex); 362 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 363 target = g_spdk_iscsi.target[i]; 364 if (target == NULL) 365 continue; 366 if (strcasecmp(tiqn, "ALL") != 0 367 && strcasecmp(tiqn, target->name) != 0) { 368 continue; 369 } 370 rc = spdk_iscsi_tgt_node_visible(target, iiqn, 371 conn->portal->group->tag); 372 if (rc == 0) { 373 continue; 374 } 375 376 /* DO SENDTARGETS */ 377 len = snprintf((char *) data + total, alloc_len - total, 378 "TargetName=%s", target->name); 379 total += len + 1; 380 381 for (j = 0; j < target->maxmap; j++) { 382 pg_tag = target->map[j].pg->tag; 383 /* skip same pg_tag */ 384 for (k = 0; k < j; k++) { 385 if (target->map[k].pg->tag == pg_tag) { 386 goto skip_pg_tag; 387 } 388 } 389 rc = spdk_iscsi_portal_grp_is_visible(target, iiqn, pg_tag); 390 if (rc == 0) { 391 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 392 "SKIP pg=%d, iqn=%s for %s from %s (%s)\n", 393 pg_tag, tiqn, target->name, iiqn, iaddr); 394 goto skip_pg_tag; 395 } 396 397 /* write to data */ 398 TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) { 399 if (pg->tag != pg_tag) 400 continue; 401 TAILQ_FOREACH(p, &pg->head, tailq) { 402 if (alloc_len - total < 1) { 403 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 404 SPDK_ERRLOG("data space small %d\n", alloc_len); 405 return total; 406 } 407 host = p->host; 408 /* wildcard? */ 409 if (strcasecmp(host, "[::]") == 0 410 || strcasecmp(host, "[*]") == 0 411 || strcasecmp(host, "0.0.0.0") == 0 412 || strcasecmp(host, "*") == 0) { 413 if ((strcasecmp(host, "[::]") == 0 414 || strcasecmp(host, "[*]") == 0) 415 && spdk_sock_is_ipv6(conn->sock)) { 416 snprintf(buf, sizeof buf, "[%s]", 417 conn->target_addr); 418 host = buf; 419 } else if ((strcasecmp(host, "0.0.0.0") == 0 420 || strcasecmp(host, "*") == 0) 421 && spdk_sock_is_ipv4(conn->sock)) { 422 snprintf(buf, sizeof buf, "%s", 423 conn->target_addr); 424 host = buf; 425 } else { 426 /* skip portal for the family */ 427 continue; 428 } 429 } 430 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 431 "TargetAddress=%s:%s,%d\n", 432 host, p->port, pg->tag); 433 len = snprintf((char *) data + total, 434 alloc_len - total, 435 "TargetAddress=%s:%s,%d", 436 host, p->port, pg->tag); 437 total += len + 1; 438 } 439 } 440 skip_pg_tag: 441 ; 442 } 443 } 444 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 445 446 return total; 447 } 448 449 struct spdk_iscsi_tgt_node * 450 spdk_iscsi_find_tgt_node(const char *target_name) 451 { 452 struct spdk_iscsi_tgt_node *target; 453 int i; 454 455 if (target_name == NULL) 456 return NULL; 457 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 458 target = g_spdk_iscsi.target[i]; 459 if (target == NULL) 460 continue; 461 if (strcasecmp(target_name, target->name) == 0) { 462 return target; 463 } 464 } 465 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "can't find target %s\n", target_name); 466 return NULL; 467 } 468 469 struct spdk_iscsi_init_grp * 470 spdk_iscsi_find_init_grp(int tag) 471 { 472 struct spdk_iscsi_init_grp *ig; 473 474 TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) { 475 if (ig->tag == tag) { 476 return ig; 477 } 478 } 479 return NULL; 480 } 481 482 static int 483 spdk_check_iscsi_name(const char *name) 484 { 485 const unsigned char *up = (const unsigned char *) name; 486 size_t n; 487 488 /* valid iSCSI name? */ 489 for (n = 0; up[n] != 0; n++) { 490 if (up[n] > 0x00U && up[n] <= 0x2cU) 491 return -1; 492 if (up[n] == 0x2fU) 493 return -1; 494 if (up[n] >= 0x3bU && up[n] <= 0x40U) 495 return -1; 496 if (up[n] >= 0x5bU && up[n] <= 0x60U) 497 return -1; 498 if (up[n] >= 0x7bU && up[n] <= 0x7fU) 499 return -1; 500 if (isspace(up[n])) 501 return -1; 502 } 503 /* valid format? */ 504 if (strncasecmp(name, "iqn.", 4) == 0) { 505 /* iqn.YYYY-MM.reversed.domain.name */ 506 if (!isdigit(up[4]) || !isdigit(up[5]) || !isdigit(up[6]) 507 || !isdigit(up[7]) || up[8] != '-' || !isdigit(up[9]) 508 || !isdigit(up[10]) || up[11] != '.') { 509 SPDK_ERRLOG("invalid iqn format. " 510 "expect \"iqn.YYYY-MM.reversed.domain.name\"\n"); 511 return -1; 512 } 513 } else if (strncasecmp(name, "eui.", 4) == 0) { 514 /* EUI-64 -> 16bytes */ 515 /* XXX */ 516 } else if (strncasecmp(name, "naa.", 4) == 0) { 517 /* 64bit -> 16bytes, 128bit -> 32bytes */ 518 /* XXX */ 519 } 520 /* OK */ 521 return 0; 522 } 523 524 static void 525 spdk_iscsi_tgt_node_destruct(struct spdk_iscsi_tgt_node *target) 526 { 527 int i; 528 529 if (target == NULL) { 530 return; 531 } 532 533 free(target->name); 534 free(target->alias); 535 spdk_scsi_dev_destruct(target->dev); 536 for (i = 0; i < target->maxmap; i++) { 537 target->map[i].pg->ref--; 538 target->map[i].ig->ref--; 539 } 540 541 pthread_mutex_destroy(&target->mutex); 542 free(target); 543 } 544 545 static int spdk_get_next_available_tgt_number(void) 546 { 547 int i; 548 549 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 550 if (g_spdk_iscsi.target[i] == NULL) 551 break; 552 } 553 return i; //Returns MAX_TARGET if none available. 554 } 555 556 static struct spdk_iscsi_tgt_node_map * 557 spdk_iscsi_tgt_node_add_map(struct spdk_iscsi_tgt_node *target, 558 int pg_tag, int ig_tag) 559 { 560 struct spdk_iscsi_tgt_node_map *map; 561 struct spdk_iscsi_portal_grp *pg; 562 struct spdk_iscsi_init_grp *ig; 563 564 if (target->maxmap >= MAX_TARGET_MAP) { 565 SPDK_ERRLOG("%s: no space for new map\n", target->name); 566 return NULL; 567 } 568 569 pthread_mutex_lock(&g_spdk_iscsi.mutex); 570 pg = spdk_iscsi_portal_grp_find_by_tag(pg_tag); 571 if (pg == NULL) { 572 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 573 SPDK_ERRLOG("%s: PortalGroup%d not found\n", target->name, pg_tag); 574 return NULL; 575 } 576 if (pg->state != GROUP_READY) { 577 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 578 SPDK_ERRLOG("%s: PortalGroup%d not active\n", target->name, pg_tag); 579 return NULL; 580 } 581 ig = spdk_iscsi_find_init_grp(ig_tag); 582 if (ig == NULL) { 583 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 584 SPDK_ERRLOG("%s: InitiatorGroup%d not found\n", target->name, ig_tag); 585 return NULL; 586 } 587 if (ig->state != GROUP_READY) { 588 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 589 SPDK_ERRLOG("%s: InitiatorGroup%d not active\n", target->name, ig_tag); 590 return NULL; 591 } 592 pg->ref++; 593 ig->ref++; 594 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 595 map = &target->map[target->maxmap]; 596 map->pg = pg; 597 map->ig = ig; 598 target->maxmap++; 599 600 return map; 601 } 602 603 _spdk_iscsi_tgt_node * 604 spdk_iscsi_tgt_node_construct(int target_index, 605 const char *name, const char *alias, 606 int *pg_tag_list, int *ig_tag_list, uint16_t num_maps, 607 char *lun_name_list[], int *lun_id_list, int num_luns, 608 int queue_depth, 609 int auth_chap_disabled, int auth_chap_required, int auth_chap_mutual, int auth_group, 610 int header_digest, int data_digest) 611 { 612 char fullname[MAX_TMPBUF], port_name[MAX_TMPBUF]; 613 struct spdk_iscsi_tgt_node *target; 614 struct spdk_iscsi_tgt_node_map *map; 615 struct spdk_iscsi_portal_grp *unique_portal_groups[SPDK_SCSI_DEV_MAX_PORTS]; 616 struct spdk_iscsi_portal_grp *pg; 617 int num_unique_portal_groups; 618 int i, j, rc; 619 620 if (auth_chap_disabled && auth_chap_required) { 621 SPDK_ERRLOG("auth_chap_disabled and auth_chap_required are mutually exclusive\n"); 622 return NULL; 623 } 624 625 if ((num_maps > MAX_TARGET_MAP) || (num_maps == 0)) { 626 SPDK_ERRLOG("num_maps = %d out of range\n", num_maps); 627 return NULL; 628 } 629 630 if (target_index == -1) 631 target_index = spdk_get_next_available_tgt_number(); 632 633 if (target_index >= MAX_ISCSI_TARGET_NODE) { 634 SPDK_ERRLOG("%d over maximum unit number\n", target_index); 635 return NULL; 636 } 637 638 if (g_spdk_iscsi.target[target_index] != NULL) { 639 SPDK_ERRLOG("tgt_node%d: duplicate unit\n", target_index); 640 return NULL; 641 } 642 643 if (name == NULL) { 644 SPDK_ERRLOG("TargetName not found\n"); 645 return NULL; 646 } 647 648 if (strncasecmp(name, "iqn.", 4) != 0 649 && strncasecmp(name, "eui.", 4) != 0 650 && strncasecmp(name, "naa.", 4) != 0) { 651 snprintf(fullname, sizeof(fullname), "%s:%s", g_spdk_iscsi.nodebase, name); 652 } else 653 snprintf(fullname, sizeof(fullname), "%s", name); 654 655 if (spdk_check_iscsi_name(fullname) != 0) { 656 SPDK_ERRLOG("TargetName %s contains an invalid character or format.\n", 657 name); 658 return NULL; 659 } 660 661 target = malloc(sizeof(*target)); 662 if (!target) { 663 SPDK_ERRLOG("could not allocate target\n"); 664 return NULL; 665 } 666 667 memset(target, 0, sizeof(*target)); 668 669 rc = pthread_mutex_init(&target->mutex, NULL); 670 if (rc != 0) { 671 SPDK_ERRLOG("tgt_node%d: mutex_init() failed\n", target->num); 672 spdk_iscsi_tgt_node_destruct(target); 673 return NULL; 674 } 675 676 target->num = target_index; 677 678 target->name = strdup(fullname); 679 if (!target->name) { 680 SPDK_ERRLOG("Could not allocate TargetName\n"); 681 spdk_iscsi_tgt_node_destruct(target); 682 return NULL; 683 } 684 685 if (alias == NULL) { 686 target->alias = NULL; 687 } else { 688 target->alias = strdup(alias); 689 if (!target->alias) { 690 SPDK_ERRLOG("Could not allocate TargetAlias\n"); 691 spdk_iscsi_tgt_node_destruct(target); 692 return NULL; 693 } 694 } 695 696 target->dev = spdk_scsi_dev_construct(name, lun_name_list, 697 lun_id_list, num_luns); 698 if (!target->dev) { 699 SPDK_ERRLOG("Could not construct SCSI device\n"); 700 spdk_iscsi_tgt_node_destruct(target); 701 return NULL; 702 } 703 704 num_unique_portal_groups = 0; 705 for (i = 0; i < num_maps; i++) { 706 map = spdk_iscsi_tgt_node_add_map(target, pg_tag_list[i], 707 ig_tag_list[i]); 708 709 if (map == NULL) { 710 SPDK_ERRLOG("could not add map to target\n"); 711 spdk_iscsi_tgt_node_destruct(target); 712 return NULL; 713 } 714 715 for (j = 0; j < num_unique_portal_groups; j++) { 716 if (unique_portal_groups[j] == map->pg) { 717 break; 718 } 719 } 720 721 if (j == SPDK_SCSI_DEV_MAX_PORTS) { 722 SPDK_ERRLOG("too many unique portal groups\n"); 723 spdk_iscsi_tgt_node_destruct(target); 724 return NULL; 725 } 726 727 if (j == num_unique_portal_groups) { 728 pg = map->pg; 729 snprintf(port_name, sizeof(port_name), "%s,t,0x%4.4x", 730 name, pg->tag); 731 spdk_scsi_dev_add_port(target->dev, pg->tag, port_name); 732 unique_portal_groups[j] = pg; 733 num_unique_portal_groups++; 734 } 735 } 736 737 target->auth_chap_disabled = auth_chap_disabled; 738 target->auth_chap_required = auth_chap_required; 739 target->auth_chap_mutual = auth_chap_mutual; 740 target->auth_group = auth_group; 741 target->header_digest = header_digest; 742 target->data_digest = data_digest; 743 744 if (queue_depth > SPDK_ISCSI_MAX_QUEUE_DEPTH) { 745 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "QueueDepth %d > Max %d. Using %d instead.\n", 746 queue_depth, SPDK_ISCSI_MAX_QUEUE_DEPTH, 747 SPDK_ISCSI_MAX_QUEUE_DEPTH); 748 queue_depth = SPDK_ISCSI_MAX_QUEUE_DEPTH; 749 } 750 target->queue_depth = queue_depth; 751 752 pthread_mutex_lock(&g_spdk_iscsi.mutex); 753 g_spdk_iscsi.ntargets++; 754 g_spdk_iscsi.target[target->num] = target; 755 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 756 757 return target; 758 } 759 760 static int 761 spdk_cf_add_iscsi_tgt_node(struct spdk_conf_section *sp) 762 { 763 char buf[MAX_TMPBUF]; 764 struct spdk_iscsi_tgt_node *target; 765 int pg_tag_list[MAX_TARGET_MAP], ig_tag_list[MAX_TARGET_MAP]; 766 int num_target_maps; 767 const char *alias, *pg_tag, *ig_tag; 768 const char *ag_tag; 769 const char *val, *name; 770 int target_num, auth_group, pg_tag_i, ig_tag_i; 771 int header_digest, data_digest; 772 int auth_chap_disabled, auth_chap_required, auth_chap_mutual; 773 int i; 774 int lun_id_list[SPDK_SCSI_DEV_MAX_LUN]; 775 char lun_name_array[SPDK_SCSI_DEV_MAX_LUN][SPDK_SCSI_LUN_MAX_NAME_LENGTH] = {}; 776 char *lun_name_list[SPDK_SCSI_DEV_MAX_LUN]; 777 int num_luns, queue_depth; 778 779 target_num = spdk_conf_section_get_num(sp); 780 781 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "add unit %d\n", target_num); 782 783 data_digest = 0; 784 header_digest = 0; 785 786 name = spdk_conf_section_get_val(sp, "TargetName"); 787 788 if (name == NULL) { 789 SPDK_ERRLOG("tgt_node%d: TargetName not found\n", target_num); 790 return -1; 791 } 792 793 alias = spdk_conf_section_get_val(sp, "TargetAlias"); 794 795 /* Setup initiator and portal group mapping */ 796 val = spdk_conf_section_get_val(sp, "Mapping"); 797 if (val == NULL) { 798 /* no map */ 799 SPDK_ERRLOG("tgt_node%d: no Mapping\n", target_num); 800 return -1; 801 } 802 803 for (i = 0; i < MAX_TARGET_MAP; i++) { 804 val = spdk_conf_section_get_nmval(sp, "Mapping", i, 0); 805 if (val == NULL) 806 break; 807 pg_tag = spdk_conf_section_get_nmval(sp, "Mapping", i, 0); 808 ig_tag = spdk_conf_section_get_nmval(sp, "Mapping", i, 1); 809 if (pg_tag == NULL || ig_tag == NULL) { 810 SPDK_ERRLOG("tgt_node%d: mapping error\n", target_num); 811 return -1; 812 } 813 if (strncasecmp(pg_tag, "PortalGroup", 814 strlen("PortalGroup")) != 0 815 || sscanf(pg_tag, "%*[^0-9]%d", &pg_tag_i) != 1) { 816 SPDK_ERRLOG("tgt_node%d: mapping portal error\n", target_num); 817 return -1; 818 } 819 if (strncasecmp(ig_tag, "InitiatorGroup", 820 strlen("InitiatorGroup")) != 0 821 || sscanf(ig_tag, "%*[^0-9]%d", &ig_tag_i) != 1) { 822 SPDK_ERRLOG("tgt_node%d: mapping initiator error\n", target_num); 823 return -1; 824 } 825 if (pg_tag_i < 1 || ig_tag_i < 1) { 826 SPDK_ERRLOG("tgt_node%d: invalid group tag\n", target_num); 827 return -1; 828 } 829 pg_tag_list[i] = pg_tag_i; 830 ig_tag_list[i] = ig_tag_i; 831 } 832 833 num_target_maps = i; 834 835 /* Setup AuthMethod */ 836 val = spdk_conf_section_get_val(sp, "AuthMethod"); 837 auth_chap_disabled = 0; 838 auth_chap_required = 0; 839 auth_chap_mutual = 0; 840 if (val != NULL) { 841 for (i = 0; ; i++) { 842 val = spdk_conf_section_get_nmval(sp, "AuthMethod", 0, i); 843 if (val == NULL) 844 break; 845 if (strcasecmp(val, "CHAP") == 0) { 846 auth_chap_required = 1; 847 } else if (strcasecmp(val, "Mutual") == 0) { 848 auth_chap_mutual = 1; 849 } else if (strcasecmp(val, "Auto") == 0) { 850 auth_chap_disabled = 0; 851 auth_chap_required = 0; 852 auth_chap_mutual = 0; 853 } else if (strcasecmp(val, "None") == 0) { 854 auth_chap_disabled = 1; 855 auth_chap_required = 0; 856 auth_chap_mutual = 0; 857 } else { 858 SPDK_ERRLOG("tgt_node%d: unknown auth\n", target_num); 859 return -1; 860 } 861 } 862 if (auth_chap_mutual && !auth_chap_required) { 863 SPDK_ERRLOG("tgt_node%d: Mutual but not CHAP\n", target_num); 864 return -1; 865 } 866 } 867 if (auth_chap_disabled == 1) { 868 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod None\n"); 869 } else if (auth_chap_required == 0) { 870 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod Auto\n"); 871 } else { 872 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod CHAP %s\n", 873 auth_chap_mutual ? "Mutual" : ""); 874 } 875 876 val = spdk_conf_section_get_val(sp, "AuthGroup"); 877 if (val == NULL) { 878 auth_group = 0; 879 } else { 880 ag_tag = val; 881 if (strcasecmp(ag_tag, "None") == 0) { 882 auth_group = 0; 883 } else { 884 if (strncasecmp(ag_tag, "AuthGroup", 885 strlen("AuthGroup")) != 0 886 || sscanf(ag_tag, "%*[^0-9]%d", &auth_group) != 1) { 887 SPDK_ERRLOG("tgt_node%d: auth group error\n", target_num); 888 return -1; 889 } 890 if (auth_group == 0) { 891 SPDK_ERRLOG("tgt_node%d: invalid auth group 0\n", target_num); 892 return -1; 893 } 894 } 895 } 896 if (auth_group == 0) { 897 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthGroup None\n"); 898 } else { 899 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthGroup AuthGroup%d\n", 900 auth_group); 901 } 902 903 val = spdk_conf_section_get_val(sp, "UseDigest"); 904 if (val != NULL) { 905 for (i = 0; ; i++) { 906 val = spdk_conf_section_get_nmval(sp, "UseDigest", 0, i); 907 if (val == NULL) 908 break; 909 if (strcasecmp(val, "Header") == 0) { 910 header_digest = 1; 911 } else if (strcasecmp(val, "Data") == 0) { 912 data_digest = 1; 913 } else if (strcasecmp(val, "Auto") == 0) { 914 header_digest = 0; 915 data_digest = 0; 916 } else { 917 SPDK_ERRLOG("tgt_node%d: unknown digest\n", target_num); 918 return -1; 919 } 920 } 921 } 922 if (header_digest == 0 && data_digest == 0) { 923 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "UseDigest Auto\n"); 924 } else { 925 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "UseDigest %s %s\n", 926 header_digest ? "Header" : "", 927 data_digest ? "Data" : ""); 928 } 929 930 val = spdk_conf_section_get_val(sp, "QueueDepth"); 931 if (val == NULL) { 932 queue_depth = SPDK_ISCSI_MAX_QUEUE_DEPTH; 933 } else { 934 queue_depth = (int) strtol(val, NULL, 10); 935 } 936 937 num_luns = 0; 938 939 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 940 snprintf(buf, sizeof(buf), "LUN%d", i); 941 val = spdk_conf_section_get_val(sp, buf); 942 if (val == NULL) { 943 continue; 944 } 945 946 snprintf(lun_name_array[num_luns], SPDK_SCSI_LUN_MAX_NAME_LENGTH, "%s", val); 947 lun_name_list[num_luns] = lun_name_array[num_luns]; 948 lun_id_list[num_luns] = i; 949 num_luns++; 950 } 951 952 if (num_luns == 0) { 953 SPDK_ERRLOG("tgt_node%d: No LUN specified for target %s.\n", target_num, name); 954 return -1; 955 } 956 957 target = spdk_iscsi_tgt_node_construct(target_num, name, alias, 958 pg_tag_list, ig_tag_list, num_target_maps, 959 lun_name_list, lun_id_list, num_luns, queue_depth, 960 auth_chap_disabled, auth_chap_required, 961 auth_chap_mutual, auth_group, 962 header_digest, data_digest); 963 964 if (target == NULL) { 965 SPDK_ERRLOG("tgt_node%d: add_iscsi_target_node error\n", target_num); 966 return -1; 967 } 968 969 spdk_scsi_dev_print(target->dev); 970 return 0; 971 } 972 973 int spdk_iscsi_init_tgt_nodes(void) 974 { 975 struct spdk_conf_section *sp; 976 int rc; 977 978 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_init_tgt_nodes\n"); 979 980 sp = spdk_conf_first_section(NULL); 981 while (sp != NULL) { 982 if (spdk_conf_section_match_prefix(sp, "TargetNode")) { 983 int tag = spdk_conf_section_get_num(sp); 984 985 if (tag > SPDK_TN_TAG_MAX) { 986 SPDK_ERRLOG("tag %d is invalid\n", tag); 987 return -1; 988 } 989 rc = spdk_cf_add_iscsi_tgt_node(sp); 990 if (rc < 0) { 991 SPDK_ERRLOG("spdk_cf_add_iscsi_tgt_node() failed\n"); 992 return -1; 993 } 994 } 995 sp = spdk_conf_next_section(sp); 996 } 997 return 0; 998 } 999 1000 int 1001 spdk_iscsi_shutdown_tgt_nodes(void) 1002 { 1003 struct spdk_iscsi_tgt_node *target; 1004 int i; 1005 1006 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1007 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1008 target = g_spdk_iscsi.target[i]; 1009 if (target == NULL) 1010 continue; 1011 spdk_iscsi_tgt_node_destruct(target); 1012 g_spdk_iscsi.ntargets--; 1013 g_spdk_iscsi.target[i] = NULL; 1014 } 1015 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1016 1017 return 0; 1018 } 1019 1020 int 1021 spdk_iscsi_shutdown_tgt_node_by_name(const char *target_name) 1022 { 1023 struct spdk_iscsi_tgt_node *target; 1024 int i = 0; 1025 int ret = -1; 1026 1027 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1028 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1029 target = g_spdk_iscsi.target[i]; 1030 if (target == NULL) 1031 continue; 1032 1033 if (strncmp(target_name, target->name, MAX_TMPBUF) == 0) { 1034 spdk_iscsi_tgt_node_destruct(target); 1035 g_spdk_iscsi.ntargets--; 1036 g_spdk_iscsi.target[i] = NULL; 1037 ret = 0; 1038 break; 1039 } 1040 } 1041 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1042 1043 return ret; 1044 } 1045 1046 int 1047 spdk_iscsi_tgt_node_cleanup_luns(struct spdk_iscsi_conn *conn, 1048 struct spdk_iscsi_tgt_node *target) 1049 { 1050 int i, maxlun; 1051 struct spdk_iscsi_task *task; 1052 1053 maxlun = spdk_scsi_dev_get_max_lun(target->dev); 1054 for (i = 0; i < maxlun; i++) { 1055 struct spdk_scsi_lun *lun = spdk_scsi_dev_get_lun(target->dev, i); 1056 1057 if (!lun) 1058 continue; 1059 1060 /* we create a fake management task per LUN to cleanup */ 1061 task = spdk_iscsi_task_get(&conn->pending_task_cnt, NULL); 1062 if (!task) { 1063 SPDK_ERRLOG("Unable to acquire task\n"); 1064 return -1; 1065 } 1066 1067 task->scsi.type = SPDK_SCSI_TASK_TYPE_MANAGE; 1068 task->scsi.target_port = conn->target_port; 1069 task->scsi.initiator_port = conn->initiator_port; 1070 task->scsi.lun = lun; 1071 task->scsi.function = SPDK_SCSI_TASK_FUNC_LUN_RESET; 1072 1073 task->scsi.cb_event = spdk_event_allocate(spdk_env_get_current_core(), 1074 process_task_mgmt_completion, conn, task); 1075 spdk_scsi_dev_queue_mgmt_task(target->dev, &task->scsi); 1076 } 1077 1078 return 0; 1079 } 1080 1081 void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group, 1082 struct spdk_iscsi_init_grp *initiator_group) 1083 { 1084 struct spdk_iscsi_tgt_node *target; 1085 int i = 0; 1086 int j = 0; 1087 int k = 0; 1088 int flag = 0; 1089 1090 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1091 target = g_spdk_iscsi.target[i]; 1092 if (target == NULL) 1093 continue; 1094 loop: 1095 flag = 0; 1096 for (j = 0; j < target->maxmap; j++) { 1097 if (portal_group) { 1098 if (target->map[j].pg->tag == portal_group->tag) { 1099 flag = 1; 1100 } 1101 } 1102 if (initiator_group) { 1103 if (target->map[j].ig->tag == initiator_group->tag) { 1104 flag = 1; 1105 } 1106 } 1107 1108 if (flag == 1) { 1109 target->map[j].pg->ref--; 1110 target->map[j].ig->ref--; 1111 for (k = j; k < target->maxmap - 1; k++) { 1112 target->map[k].pg = target->map[k + 1].pg; 1113 target->map[k].ig = target->map[k + 1].ig; 1114 } 1115 target->map[target->maxmap - 1].pg = NULL; 1116 target->map[target->maxmap - 1].ig = NULL; 1117 target->maxmap -= 1; 1118 goto loop; 1119 } 1120 } 1121 } 1122 } 1123