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, lun_id_list, num_luns, 697 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 698 699 if (!target->dev) { 700 SPDK_ERRLOG("Could not construct SCSI device\n"); 701 spdk_iscsi_tgt_node_destruct(target); 702 return NULL; 703 } 704 705 num_unique_portal_groups = 0; 706 for (i = 0; i < num_maps; i++) { 707 map = spdk_iscsi_tgt_node_add_map(target, pg_tag_list[i], 708 ig_tag_list[i]); 709 710 if (map == NULL) { 711 SPDK_ERRLOG("could not add map to target\n"); 712 spdk_iscsi_tgt_node_destruct(target); 713 return NULL; 714 } 715 716 for (j = 0; j < num_unique_portal_groups; j++) { 717 if (unique_portal_groups[j] == map->pg) { 718 break; 719 } 720 } 721 722 if (j == SPDK_SCSI_DEV_MAX_PORTS) { 723 SPDK_ERRLOG("too many unique portal groups\n"); 724 spdk_iscsi_tgt_node_destruct(target); 725 return NULL; 726 } 727 728 if (j == num_unique_portal_groups) { 729 pg = map->pg; 730 snprintf(port_name, sizeof(port_name), "%s,t,0x%4.4x", 731 name, pg->tag); 732 spdk_scsi_dev_add_port(target->dev, pg->tag, port_name); 733 unique_portal_groups[j] = pg; 734 num_unique_portal_groups++; 735 } 736 } 737 738 target->auth_chap_disabled = auth_chap_disabled; 739 target->auth_chap_required = auth_chap_required; 740 target->auth_chap_mutual = auth_chap_mutual; 741 target->auth_group = auth_group; 742 target->header_digest = header_digest; 743 target->data_digest = data_digest; 744 745 if (queue_depth > SPDK_ISCSI_MAX_QUEUE_DEPTH) { 746 SPDK_TRACELOG(SPDK_TRACE_ISCSI, "QueueDepth %d > Max %d. Using %d instead.\n", 747 queue_depth, SPDK_ISCSI_MAX_QUEUE_DEPTH, 748 SPDK_ISCSI_MAX_QUEUE_DEPTH); 749 queue_depth = SPDK_ISCSI_MAX_QUEUE_DEPTH; 750 } 751 target->queue_depth = queue_depth; 752 753 pthread_mutex_lock(&g_spdk_iscsi.mutex); 754 g_spdk_iscsi.ntargets++; 755 g_spdk_iscsi.target[target->num] = target; 756 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 757 758 return target; 759 } 760 761 static int 762 spdk_cf_add_iscsi_tgt_node(struct spdk_conf_section *sp) 763 { 764 char buf[MAX_TMPBUF]; 765 struct spdk_iscsi_tgt_node *target; 766 int pg_tag_list[MAX_TARGET_MAP], ig_tag_list[MAX_TARGET_MAP]; 767 int num_target_maps; 768 const char *alias, *pg_tag, *ig_tag; 769 const char *ag_tag; 770 const char *val, *name; 771 int target_num, auth_group, pg_tag_i, ig_tag_i; 772 int header_digest, data_digest; 773 int auth_chap_disabled, auth_chap_required, auth_chap_mutual; 774 int i; 775 int lun_id_list[SPDK_SCSI_DEV_MAX_LUN]; 776 char lun_name_array[SPDK_SCSI_DEV_MAX_LUN][SPDK_SCSI_LUN_MAX_NAME_LENGTH] = {}; 777 char *lun_name_list[SPDK_SCSI_DEV_MAX_LUN]; 778 int num_luns, queue_depth; 779 780 target_num = spdk_conf_section_get_num(sp); 781 782 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "add unit %d\n", target_num); 783 784 data_digest = 0; 785 header_digest = 0; 786 787 name = spdk_conf_section_get_val(sp, "TargetName"); 788 789 if (name == NULL) { 790 SPDK_ERRLOG("tgt_node%d: TargetName not found\n", target_num); 791 return -1; 792 } 793 794 alias = spdk_conf_section_get_val(sp, "TargetAlias"); 795 796 /* Setup initiator and portal group mapping */ 797 val = spdk_conf_section_get_val(sp, "Mapping"); 798 if (val == NULL) { 799 /* no map */ 800 SPDK_ERRLOG("tgt_node%d: no Mapping\n", target_num); 801 return -1; 802 } 803 804 for (i = 0; i < MAX_TARGET_MAP; i++) { 805 val = spdk_conf_section_get_nmval(sp, "Mapping", i, 0); 806 if (val == NULL) 807 break; 808 pg_tag = spdk_conf_section_get_nmval(sp, "Mapping", i, 0); 809 ig_tag = spdk_conf_section_get_nmval(sp, "Mapping", i, 1); 810 if (pg_tag == NULL || ig_tag == NULL) { 811 SPDK_ERRLOG("tgt_node%d: mapping error\n", target_num); 812 return -1; 813 } 814 if (strncasecmp(pg_tag, "PortalGroup", 815 strlen("PortalGroup")) != 0 816 || sscanf(pg_tag, "%*[^0-9]%d", &pg_tag_i) != 1) { 817 SPDK_ERRLOG("tgt_node%d: mapping portal error\n", target_num); 818 return -1; 819 } 820 if (strncasecmp(ig_tag, "InitiatorGroup", 821 strlen("InitiatorGroup")) != 0 822 || sscanf(ig_tag, "%*[^0-9]%d", &ig_tag_i) != 1) { 823 SPDK_ERRLOG("tgt_node%d: mapping initiator error\n", target_num); 824 return -1; 825 } 826 if (pg_tag_i < 1 || ig_tag_i < 1) { 827 SPDK_ERRLOG("tgt_node%d: invalid group tag\n", target_num); 828 return -1; 829 } 830 pg_tag_list[i] = pg_tag_i; 831 ig_tag_list[i] = ig_tag_i; 832 } 833 834 num_target_maps = i; 835 836 /* Setup AuthMethod */ 837 val = spdk_conf_section_get_val(sp, "AuthMethod"); 838 auth_chap_disabled = 0; 839 auth_chap_required = 0; 840 auth_chap_mutual = 0; 841 if (val != NULL) { 842 for (i = 0; ; i++) { 843 val = spdk_conf_section_get_nmval(sp, "AuthMethod", 0, i); 844 if (val == NULL) 845 break; 846 if (strcasecmp(val, "CHAP") == 0) { 847 auth_chap_required = 1; 848 } else if (strcasecmp(val, "Mutual") == 0) { 849 auth_chap_mutual = 1; 850 } else if (strcasecmp(val, "Auto") == 0) { 851 auth_chap_disabled = 0; 852 auth_chap_required = 0; 853 auth_chap_mutual = 0; 854 } else if (strcasecmp(val, "None") == 0) { 855 auth_chap_disabled = 1; 856 auth_chap_required = 0; 857 auth_chap_mutual = 0; 858 } else { 859 SPDK_ERRLOG("tgt_node%d: unknown auth\n", target_num); 860 return -1; 861 } 862 } 863 if (auth_chap_mutual && !auth_chap_required) { 864 SPDK_ERRLOG("tgt_node%d: Mutual but not CHAP\n", target_num); 865 return -1; 866 } 867 } 868 if (auth_chap_disabled == 1) { 869 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod None\n"); 870 } else if (auth_chap_required == 0) { 871 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod Auto\n"); 872 } else { 873 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthMethod CHAP %s\n", 874 auth_chap_mutual ? "Mutual" : ""); 875 } 876 877 val = spdk_conf_section_get_val(sp, "AuthGroup"); 878 if (val == NULL) { 879 auth_group = 0; 880 } else { 881 ag_tag = val; 882 if (strcasecmp(ag_tag, "None") == 0) { 883 auth_group = 0; 884 } else { 885 if (strncasecmp(ag_tag, "AuthGroup", 886 strlen("AuthGroup")) != 0 887 || sscanf(ag_tag, "%*[^0-9]%d", &auth_group) != 1) { 888 SPDK_ERRLOG("tgt_node%d: auth group error\n", target_num); 889 return -1; 890 } 891 if (auth_group == 0) { 892 SPDK_ERRLOG("tgt_node%d: invalid auth group 0\n", target_num); 893 return -1; 894 } 895 } 896 } 897 if (auth_group == 0) { 898 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthGroup None\n"); 899 } else { 900 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthGroup AuthGroup%d\n", 901 auth_group); 902 } 903 904 val = spdk_conf_section_get_val(sp, "UseDigest"); 905 if (val != NULL) { 906 for (i = 0; ; i++) { 907 val = spdk_conf_section_get_nmval(sp, "UseDigest", 0, i); 908 if (val == NULL) 909 break; 910 if (strcasecmp(val, "Header") == 0) { 911 header_digest = 1; 912 } else if (strcasecmp(val, "Data") == 0) { 913 data_digest = 1; 914 } else if (strcasecmp(val, "Auto") == 0) { 915 header_digest = 0; 916 data_digest = 0; 917 } else { 918 SPDK_ERRLOG("tgt_node%d: unknown digest\n", target_num); 919 return -1; 920 } 921 } 922 } 923 if (header_digest == 0 && data_digest == 0) { 924 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "UseDigest Auto\n"); 925 } else { 926 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "UseDigest %s %s\n", 927 header_digest ? "Header" : "", 928 data_digest ? "Data" : ""); 929 } 930 931 val = spdk_conf_section_get_val(sp, "QueueDepth"); 932 if (val == NULL) { 933 queue_depth = SPDK_ISCSI_MAX_QUEUE_DEPTH; 934 } else { 935 queue_depth = (int) strtol(val, NULL, 10); 936 } 937 938 num_luns = 0; 939 940 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 941 snprintf(buf, sizeof(buf), "LUN%d", i); 942 val = spdk_conf_section_get_val(sp, buf); 943 if (val == NULL) { 944 continue; 945 } 946 947 snprintf(lun_name_array[num_luns], SPDK_SCSI_LUN_MAX_NAME_LENGTH, "%s", val); 948 lun_name_list[num_luns] = lun_name_array[num_luns]; 949 lun_id_list[num_luns] = i; 950 num_luns++; 951 } 952 953 if (num_luns == 0) { 954 SPDK_ERRLOG("tgt_node%d: No LUN specified for target %s.\n", target_num, name); 955 return -1; 956 } 957 958 target = spdk_iscsi_tgt_node_construct(target_num, name, alias, 959 pg_tag_list, ig_tag_list, num_target_maps, 960 lun_name_list, lun_id_list, num_luns, queue_depth, 961 auth_chap_disabled, auth_chap_required, 962 auth_chap_mutual, auth_group, 963 header_digest, data_digest); 964 965 if (target == NULL) { 966 SPDK_ERRLOG("tgt_node%d: add_iscsi_target_node error\n", target_num); 967 return -1; 968 } 969 970 spdk_scsi_dev_print(target->dev); 971 return 0; 972 } 973 974 int spdk_iscsi_init_tgt_nodes(void) 975 { 976 struct spdk_conf_section *sp; 977 int rc; 978 979 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_init_tgt_nodes\n"); 980 981 sp = spdk_conf_first_section(NULL); 982 while (sp != NULL) { 983 if (spdk_conf_section_match_prefix(sp, "TargetNode")) { 984 int tag = spdk_conf_section_get_num(sp); 985 986 if (tag > SPDK_TN_TAG_MAX) { 987 SPDK_ERRLOG("tag %d is invalid\n", tag); 988 return -1; 989 } 990 rc = spdk_cf_add_iscsi_tgt_node(sp); 991 if (rc < 0) { 992 SPDK_ERRLOG("spdk_cf_add_iscsi_tgt_node() failed\n"); 993 return -1; 994 } 995 } 996 sp = spdk_conf_next_section(sp); 997 } 998 return 0; 999 } 1000 1001 int 1002 spdk_iscsi_shutdown_tgt_nodes(void) 1003 { 1004 struct spdk_iscsi_tgt_node *target; 1005 int i; 1006 1007 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1008 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1009 target = g_spdk_iscsi.target[i]; 1010 if (target == NULL) 1011 continue; 1012 spdk_iscsi_tgt_node_destruct(target); 1013 g_spdk_iscsi.ntargets--; 1014 g_spdk_iscsi.target[i] = NULL; 1015 } 1016 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1017 1018 return 0; 1019 } 1020 1021 int 1022 spdk_iscsi_shutdown_tgt_node_by_name(const char *target_name) 1023 { 1024 struct spdk_iscsi_tgt_node *target; 1025 int i = 0; 1026 int ret = -1; 1027 1028 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1029 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1030 target = g_spdk_iscsi.target[i]; 1031 if (target == NULL) 1032 continue; 1033 1034 if (strncmp(target_name, target->name, MAX_TMPBUF) == 0) { 1035 spdk_iscsi_tgt_node_destruct(target); 1036 g_spdk_iscsi.ntargets--; 1037 g_spdk_iscsi.target[i] = NULL; 1038 ret = 0; 1039 break; 1040 } 1041 } 1042 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1043 1044 return ret; 1045 } 1046 1047 int 1048 spdk_iscsi_tgt_node_cleanup_luns(struct spdk_iscsi_conn *conn, 1049 struct spdk_iscsi_tgt_node *target) 1050 { 1051 int i, maxlun; 1052 struct spdk_iscsi_task *task; 1053 1054 maxlun = spdk_scsi_dev_get_max_lun(target->dev); 1055 for (i = 0; i < maxlun; i++) { 1056 struct spdk_scsi_lun *lun = spdk_scsi_dev_get_lun(target->dev, i); 1057 1058 if (!lun) 1059 continue; 1060 1061 /* we create a fake management task per LUN to cleanup */ 1062 task = spdk_iscsi_task_get(conn, NULL, spdk_iscsi_task_mgmt_cpl); 1063 if (!task) { 1064 SPDK_ERRLOG("Unable to acquire task\n"); 1065 return -1; 1066 } 1067 1068 task->scsi.target_port = conn->target_port; 1069 task->scsi.initiator_port = conn->initiator_port; 1070 task->scsi.lun = lun; 1071 1072 spdk_scsi_dev_queue_mgmt_task(target->dev, &task->scsi, SPDK_SCSI_TASK_FUNC_LUN_RESET); 1073 } 1074 1075 return 0; 1076 } 1077 1078 void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group, 1079 struct spdk_iscsi_init_grp *initiator_group) 1080 { 1081 struct spdk_iscsi_tgt_node *target; 1082 int i = 0; 1083 int j = 0; 1084 int k = 0; 1085 int flag = 0; 1086 1087 for (i = 0; i < MAX_ISCSI_TARGET_NODE; i++) { 1088 target = g_spdk_iscsi.target[i]; 1089 if (target == NULL) 1090 continue; 1091 loop: 1092 flag = 0; 1093 for (j = 0; j < target->maxmap; j++) { 1094 if (portal_group) { 1095 if (target->map[j].pg->tag == portal_group->tag) { 1096 flag = 1; 1097 } 1098 } 1099 if (initiator_group) { 1100 if (target->map[j].ig->tag == initiator_group->tag) { 1101 flag = 1; 1102 } 1103 } 1104 1105 if (flag == 1) { 1106 target->map[j].pg->ref--; 1107 target->map[j].ig->ref--; 1108 for (k = j; k < target->maxmap - 1; k++) { 1109 target->map[k].pg = target->map[k + 1].pg; 1110 target->map[k].ig = target->map[k + 1].ig; 1111 } 1112 target->map[target->maxmap - 1].pg = NULL; 1113 target->map[target->maxmap - 1].ig = NULL; 1114 target->maxmap -= 1; 1115 goto loop; 1116 } 1117 } 1118 } 1119 } 1120