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/conf.h" 38 #include "spdk/string.h" 39 40 #include "spdk/log.h" 41 42 #include "iscsi/iscsi.h" 43 #include "iscsi/init_grp.h" 44 45 static struct spdk_iscsi_init_grp * 46 iscsi_init_grp_create(int tag) 47 { 48 struct spdk_iscsi_init_grp *ig; 49 50 ig = calloc(1, sizeof(*ig)); 51 if (ig == NULL) { 52 SPDK_ERRLOG("calloc() failed for initiator group\n"); 53 return NULL; 54 } 55 56 ig->tag = tag; 57 TAILQ_INIT(&ig->initiator_head); 58 TAILQ_INIT(&ig->netmask_head); 59 return ig; 60 } 61 62 static struct spdk_iscsi_initiator_name * 63 iscsi_init_grp_find_initiator(struct spdk_iscsi_init_grp *ig, char *name) 64 { 65 struct spdk_iscsi_initiator_name *iname; 66 67 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 68 if (!strcmp(iname->name, name)) { 69 return iname; 70 } 71 } 72 return NULL; 73 } 74 75 static int 76 iscsi_init_grp_add_initiator(struct spdk_iscsi_init_grp *ig, char *name) 77 { 78 struct spdk_iscsi_initiator_name *iname; 79 char *p; 80 size_t len; 81 82 if (ig->ninitiators >= MAX_INITIATOR) { 83 SPDK_ERRLOG("> MAX_INITIATOR(=%d) is not allowed\n", MAX_INITIATOR); 84 return -EPERM; 85 } 86 87 len = strlen(name); 88 if (len > MAX_INITIATOR_NAME) { 89 SPDK_ERRLOG("Initiator Name is larger than 223 bytes\n"); 90 return -EINVAL; 91 } 92 93 iname = iscsi_init_grp_find_initiator(ig, name); 94 if (iname != NULL) { 95 return -EEXIST; 96 } 97 98 iname = calloc(1, sizeof(*iname)); 99 if (iname == NULL) { 100 SPDK_ERRLOG("malloc() failed for initiator name str\n"); 101 return -ENOMEM; 102 } 103 104 memcpy(iname->name, name, len); 105 106 /* Replace "ALL" by "ANY" if set */ 107 p = strstr(iname->name, "ALL"); 108 if (p != NULL) { 109 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL"); 110 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY"); 111 memcpy(p, "ANY", 3); 112 } 113 114 TAILQ_INSERT_TAIL(&ig->initiator_head, iname, tailq); 115 ig->ninitiators++; 116 117 SPDK_DEBUGLOG(iscsi, "InitiatorName %s\n", name); 118 return 0; 119 } 120 121 static int 122 iscsi_init_grp_delete_initiator(struct spdk_iscsi_init_grp *ig, char *name) 123 { 124 struct spdk_iscsi_initiator_name *iname; 125 126 iname = iscsi_init_grp_find_initiator(ig, name); 127 if (iname == NULL) { 128 return -ENOENT; 129 } 130 131 TAILQ_REMOVE(&ig->initiator_head, iname, tailq); 132 ig->ninitiators--; 133 free(iname); 134 return 0; 135 } 136 137 static int 138 iscsi_init_grp_add_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, 139 char **inames) 140 { 141 int i; 142 int rc; 143 144 for (i = 0; i < num_inames; i++) { 145 rc = iscsi_init_grp_add_initiator(ig, inames[i]); 146 if (rc < 0) { 147 goto cleanup; 148 } 149 } 150 return 0; 151 152 cleanup: 153 for (; i > 0; --i) { 154 iscsi_init_grp_delete_initiator(ig, inames[i - 1]); 155 } 156 return rc; 157 } 158 159 static void 160 iscsi_init_grp_delete_all_initiators(struct spdk_iscsi_init_grp *ig) 161 { 162 struct spdk_iscsi_initiator_name *iname, *tmp; 163 164 TAILQ_FOREACH_SAFE(iname, &ig->initiator_head, tailq, tmp) { 165 TAILQ_REMOVE(&ig->initiator_head, iname, tailq); 166 ig->ninitiators--; 167 free(iname); 168 } 169 } 170 171 static int 172 iscsi_init_grp_delete_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, char **inames) 173 { 174 int i; 175 int rc; 176 177 for (i = 0; i < num_inames; i++) { 178 rc = iscsi_init_grp_delete_initiator(ig, inames[i]); 179 if (rc < 0) { 180 goto cleanup; 181 } 182 } 183 return 0; 184 185 cleanup: 186 for (; i > 0; --i) { 187 rc = iscsi_init_grp_add_initiator(ig, inames[i - 1]); 188 if (rc != 0) { 189 iscsi_init_grp_delete_all_initiators(ig); 190 break; 191 } 192 } 193 return -1; 194 } 195 196 static struct spdk_iscsi_initiator_netmask * 197 iscsi_init_grp_find_netmask(struct spdk_iscsi_init_grp *ig, const char *mask) 198 { 199 struct spdk_iscsi_initiator_netmask *netmask; 200 201 TAILQ_FOREACH(netmask, &ig->netmask_head, tailq) { 202 if (!strcmp(netmask->mask, mask)) { 203 return netmask; 204 } 205 } 206 return NULL; 207 } 208 209 static int 210 iscsi_init_grp_add_netmask(struct spdk_iscsi_init_grp *ig, char *mask) 211 { 212 struct spdk_iscsi_initiator_netmask *imask; 213 char *p; 214 size_t len; 215 216 if (ig->nnetmasks >= MAX_NETMASK) { 217 SPDK_ERRLOG("> MAX_NETMASK(=%d) is not allowed\n", MAX_NETMASK); 218 return -EPERM; 219 } 220 221 len = strlen(mask); 222 if (len > MAX_INITIATOR_ADDR) { 223 SPDK_ERRLOG("Initiator Name is larger than %d bytes\n", MAX_INITIATOR_ADDR); 224 return -EINVAL; 225 } 226 227 imask = iscsi_init_grp_find_netmask(ig, mask); 228 if (imask != NULL) { 229 return -EEXIST; 230 } 231 232 imask = calloc(1, sizeof(*imask)); 233 if (imask == NULL) { 234 SPDK_ERRLOG("malloc() failed for inititator mask str\n"); 235 return -ENOMEM; 236 } 237 238 memcpy(imask->mask, mask, len); 239 240 /* Replace "ALL" by "ANY" if set */ 241 p = strstr(imask->mask, "ALL"); 242 if (p != NULL) { 243 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL"); 244 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY"); 245 memcpy(p, "ANY", 3); 246 } 247 248 TAILQ_INSERT_TAIL(&ig->netmask_head, imask, tailq); 249 ig->nnetmasks++; 250 251 SPDK_DEBUGLOG(iscsi, "Netmask %s\n", mask); 252 return 0; 253 } 254 255 static int 256 iscsi_init_grp_delete_netmask(struct spdk_iscsi_init_grp *ig, char *mask) 257 { 258 struct spdk_iscsi_initiator_netmask *imask; 259 260 imask = iscsi_init_grp_find_netmask(ig, mask); 261 if (imask == NULL) { 262 return -ENOENT; 263 } 264 265 TAILQ_REMOVE(&ig->netmask_head, imask, tailq); 266 ig->nnetmasks--; 267 free(imask); 268 return 0; 269 } 270 271 static int 272 iscsi_init_grp_add_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks) 273 { 274 int i; 275 int rc; 276 277 for (i = 0; i < num_imasks; i++) { 278 rc = iscsi_init_grp_add_netmask(ig, imasks[i]); 279 if (rc != 0) { 280 goto cleanup; 281 } 282 } 283 return 0; 284 285 cleanup: 286 for (; i > 0; --i) { 287 iscsi_init_grp_delete_netmask(ig, imasks[i - 1]); 288 } 289 return rc; 290 } 291 292 static void 293 iscsi_init_grp_delete_all_netmasks(struct spdk_iscsi_init_grp *ig) 294 { 295 struct spdk_iscsi_initiator_netmask *imask, *tmp; 296 297 TAILQ_FOREACH_SAFE(imask, &ig->netmask_head, tailq, tmp) { 298 TAILQ_REMOVE(&ig->netmask_head, imask, tailq); 299 ig->nnetmasks--; 300 free(imask); 301 } 302 } 303 304 static int 305 iscsi_init_grp_delete_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks) 306 { 307 int i; 308 int rc; 309 310 for (i = 0; i < num_imasks; i++) { 311 rc = iscsi_init_grp_delete_netmask(ig, imasks[i]); 312 if (rc != 0) { 313 goto cleanup; 314 } 315 } 316 return 0; 317 318 cleanup: 319 for (; i > 0; --i) { 320 rc = iscsi_init_grp_add_netmask(ig, imasks[i - 1]); 321 if (rc != 0) { 322 iscsi_init_grp_delete_all_netmasks(ig); 323 break; 324 } 325 } 326 return -1; 327 } 328 329 /* Read spdk iscsi target's config file and create initiator group */ 330 static int 331 iscsi_parse_init_grp(struct spdk_conf_section *sp) 332 { 333 int i, rc = 0; 334 const char *val = NULL; 335 int num_initiator_names; 336 int num_initiator_masks; 337 char **initiators = NULL, **netmasks = NULL; 338 int tag = spdk_conf_section_get_num(sp); 339 340 SPDK_DEBUGLOG(iscsi, "add initiator group %d\n", tag); 341 342 val = spdk_conf_section_get_val(sp, "Comment"); 343 if (val != NULL) { 344 SPDK_DEBUGLOG(iscsi, "Comment %s\n", val); 345 } 346 347 /* counts number of definitions */ 348 for (i = 0; ; i++) { 349 val = spdk_conf_section_get_nval(sp, "InitiatorName", i); 350 if (val == NULL) { 351 break; 352 } 353 } 354 if (i == 0) { 355 SPDK_ERRLOG("num_initiator_names = 0\n"); 356 return -EINVAL; 357 } 358 num_initiator_names = i; 359 if (num_initiator_names > MAX_INITIATOR) { 360 SPDK_ERRLOG("%d > MAX_INITIATOR\n", num_initiator_names); 361 return -E2BIG; 362 } 363 for (i = 0; ; i++) { 364 val = spdk_conf_section_get_nval(sp, "Netmask", i); 365 if (val == NULL) { 366 break; 367 } 368 } 369 if (i == 0) { 370 SPDK_ERRLOG("num_initiator_mask = 0\n"); 371 return -EINVAL; 372 } 373 num_initiator_masks = i; 374 if (num_initiator_masks > MAX_NETMASK) { 375 SPDK_ERRLOG("%d > MAX_NETMASK\n", num_initiator_masks); 376 return -E2BIG; 377 } 378 379 initiators = calloc(num_initiator_names, sizeof(char *)); 380 if (!initiators) { 381 SPDK_ERRLOG("calloc() failed for temp initiator name array\n"); 382 return -ENOMEM; 383 } 384 for (i = 0; i < num_initiator_names; i++) { 385 val = spdk_conf_section_get_nval(sp, "InitiatorName", i); 386 if (!val) { 387 SPDK_ERRLOG("InitiatorName %d not found\n", i); 388 rc = -EINVAL; 389 goto cleanup; 390 } 391 SPDK_DEBUGLOG(iscsi, "InitiatorName %s\n", val); 392 initiators[i] = strdup(val); 393 if (!initiators[i]) { 394 SPDK_ERRLOG("strdup() failed for temp initiator name\n"); 395 rc = -ENOMEM; 396 goto cleanup; 397 } 398 } 399 netmasks = calloc(num_initiator_masks, sizeof(char *)); 400 if (!netmasks) { 401 SPDK_ERRLOG("malloc() failed for portal group\n"); 402 rc = -ENOMEM; 403 goto cleanup; 404 } 405 for (i = 0; i < num_initiator_masks; i++) { 406 val = spdk_conf_section_get_nval(sp, "Netmask", i); 407 if (!val) { 408 SPDK_ERRLOG("Netmask %d not found\n", i); 409 rc = -EINVAL; 410 goto cleanup; 411 } 412 SPDK_DEBUGLOG(iscsi, "Netmask %s\n", val); 413 netmasks[i] = strdup(val); 414 if (!netmasks[i]) { 415 SPDK_ERRLOG("strdup() failed for temp initiator mask\n"); 416 rc = -ENOMEM; 417 goto cleanup; 418 } 419 } 420 421 rc = iscsi_init_grp_create_from_initiator_list(tag, 422 num_initiator_names, initiators, num_initiator_masks, netmasks); 423 424 cleanup: 425 if (initiators) { 426 for (i = 0; i < num_initiator_names; i++) { 427 if (initiators[i]) { 428 free(initiators[i]); 429 } 430 } 431 free(initiators); 432 } 433 if (netmasks) { 434 for (i = 0; i < num_initiator_masks; i++) { 435 if (netmasks[i]) { 436 free(netmasks[i]); 437 } 438 } 439 free(netmasks); 440 } 441 return rc; 442 } 443 444 int 445 iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig) 446 { 447 struct spdk_iscsi_init_grp *tmp; 448 int rc = -1; 449 450 assert(ig != NULL); 451 452 pthread_mutex_lock(&g_iscsi.mutex); 453 tmp = iscsi_init_grp_find_by_tag(ig->tag); 454 if (tmp == NULL) { 455 TAILQ_INSERT_TAIL(&g_iscsi.ig_head, ig, tailq); 456 rc = 0; 457 } 458 pthread_mutex_unlock(&g_iscsi.mutex); 459 460 return rc; 461 } 462 463 /* 464 * Create initiator group from list of initiator ip/hostnames and netmasks 465 * The initiator hostname/netmask lists are allocated by the caller on the 466 * heap. Freed later by common initiator_group_destroy() code 467 */ 468 int 469 iscsi_init_grp_create_from_initiator_list(int tag, 470 int num_initiator_names, 471 char **initiator_names, 472 int num_initiator_masks, 473 char **initiator_masks) 474 { 475 int rc = -1; 476 struct spdk_iscsi_init_grp *ig = NULL; 477 478 SPDK_DEBUGLOG(iscsi, 479 "add initiator group (from initiator list) tag=%d, #initiators=%d, #masks=%d\n", 480 tag, num_initiator_names, num_initiator_masks); 481 482 ig = iscsi_init_grp_create(tag); 483 if (!ig) { 484 SPDK_ERRLOG("initiator group create error (%d)\n", tag); 485 return rc; 486 } 487 488 rc = iscsi_init_grp_add_initiators(ig, num_initiator_names, 489 initiator_names); 490 if (rc < 0) { 491 SPDK_ERRLOG("add initiator name error\n"); 492 goto cleanup; 493 } 494 495 rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks, 496 initiator_masks); 497 if (rc < 0) { 498 SPDK_ERRLOG("add initiator netmask error\n"); 499 goto cleanup; 500 } 501 502 rc = iscsi_init_grp_register(ig); 503 if (rc < 0) { 504 SPDK_ERRLOG("initiator group register error (%d)\n", tag); 505 goto cleanup; 506 } 507 return 0; 508 509 cleanup: 510 iscsi_init_grp_destroy(ig); 511 return rc; 512 } 513 514 int 515 iscsi_init_grp_add_initiators_from_initiator_list(int tag, 516 int num_initiator_names, 517 char **initiator_names, 518 int num_initiator_masks, 519 char **initiator_masks) 520 { 521 int rc = -1; 522 struct spdk_iscsi_init_grp *ig; 523 524 SPDK_DEBUGLOG(iscsi, 525 "add initiator to initiator group: tag=%d, #initiators=%d, #masks=%d\n", 526 tag, num_initiator_names, num_initiator_masks); 527 528 pthread_mutex_lock(&g_iscsi.mutex); 529 ig = iscsi_init_grp_find_by_tag(tag); 530 if (!ig) { 531 pthread_mutex_unlock(&g_iscsi.mutex); 532 SPDK_ERRLOG("initiator group (%d) is not found\n", tag); 533 return rc; 534 } 535 536 rc = iscsi_init_grp_add_initiators(ig, num_initiator_names, 537 initiator_names); 538 if (rc < 0) { 539 SPDK_ERRLOG("add initiator name error\n"); 540 goto error; 541 } 542 543 rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks, 544 initiator_masks); 545 if (rc < 0) { 546 SPDK_ERRLOG("add initiator netmask error\n"); 547 iscsi_init_grp_delete_initiators(ig, num_initiator_names, 548 initiator_names); 549 } 550 551 error: 552 pthread_mutex_unlock(&g_iscsi.mutex); 553 return rc; 554 } 555 556 int 557 iscsi_init_grp_delete_initiators_from_initiator_list(int tag, 558 int num_initiator_names, 559 char **initiator_names, 560 int num_initiator_masks, 561 char **initiator_masks) 562 { 563 int rc = -1; 564 struct spdk_iscsi_init_grp *ig; 565 566 SPDK_DEBUGLOG(iscsi, 567 "delete initiator from initiator group: tag=%d, #initiators=%d, #masks=%d\n", 568 tag, num_initiator_names, num_initiator_masks); 569 570 pthread_mutex_lock(&g_iscsi.mutex); 571 ig = iscsi_init_grp_find_by_tag(tag); 572 if (!ig) { 573 pthread_mutex_unlock(&g_iscsi.mutex); 574 SPDK_ERRLOG("initiator group (%d) is not found\n", tag); 575 return rc; 576 } 577 578 rc = iscsi_init_grp_delete_initiators(ig, num_initiator_names, 579 initiator_names); 580 if (rc < 0) { 581 SPDK_ERRLOG("delete initiator name error\n"); 582 goto error; 583 } 584 585 rc = iscsi_init_grp_delete_netmasks(ig, num_initiator_masks, 586 initiator_masks); 587 if (rc < 0) { 588 SPDK_ERRLOG("delete initiator netmask error\n"); 589 iscsi_init_grp_add_initiators(ig, num_initiator_names, 590 initiator_names); 591 goto error; 592 } 593 594 error: 595 pthread_mutex_unlock(&g_iscsi.mutex); 596 return rc; 597 } 598 599 void 600 iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig) 601 { 602 if (!ig) { 603 return; 604 } 605 606 iscsi_init_grp_delete_all_initiators(ig); 607 iscsi_init_grp_delete_all_netmasks(ig); 608 free(ig); 609 }; 610 611 struct spdk_iscsi_init_grp * 612 iscsi_init_grp_find_by_tag(int tag) 613 { 614 struct spdk_iscsi_init_grp *ig; 615 616 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 617 if (ig->tag == tag) { 618 return ig; 619 } 620 } 621 622 return NULL; 623 } 624 625 int 626 iscsi_parse_init_grps(void) 627 { 628 struct spdk_conf_section *sp; 629 int rc; 630 631 sp = spdk_conf_first_section(NULL); 632 while (sp != NULL) { 633 if (spdk_conf_section_match_prefix(sp, "InitiatorGroup")) { 634 if (spdk_conf_section_get_num(sp) == 0) { 635 SPDK_ERRLOG("Group 0 is invalid\n"); 636 return -1; 637 } 638 rc = iscsi_parse_init_grp(sp); 639 if (rc < 0) { 640 SPDK_ERRLOG("parse_init_group() failed\n"); 641 return -1; 642 } 643 } 644 sp = spdk_conf_next_section(sp); 645 } 646 return 0; 647 } 648 649 void 650 iscsi_init_grps_destroy(void) 651 { 652 struct spdk_iscsi_init_grp *ig, *tmp; 653 654 SPDK_DEBUGLOG(iscsi, "iscsi_init_grp_array_destroy\n"); 655 pthread_mutex_lock(&g_iscsi.mutex); 656 TAILQ_FOREACH_SAFE(ig, &g_iscsi.ig_head, tailq, tmp) { 657 TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq); 658 iscsi_init_grp_destroy(ig); 659 } 660 pthread_mutex_unlock(&g_iscsi.mutex); 661 } 662 663 struct spdk_iscsi_init_grp * 664 iscsi_init_grp_unregister(int tag) 665 { 666 struct spdk_iscsi_init_grp *ig; 667 668 pthread_mutex_lock(&g_iscsi.mutex); 669 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 670 if (ig->tag == tag) { 671 TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq); 672 pthread_mutex_unlock(&g_iscsi.mutex); 673 return ig; 674 } 675 } 676 pthread_mutex_unlock(&g_iscsi.mutex); 677 return NULL; 678 } 679 680 static const char *initiator_group_section = \ 681 "\n" 682 "# Users must change the InitiatorGroup section(s) to match the IP\n" 683 "# addresses and initiator configuration in their environment.\n" 684 "# Netmask can be used to specify a single IP address or a range of IP addresses\n" 685 "# Netmask 192.168.1.20 <== single IP address\n" 686 "# Netmask 192.168.1.0/24 <== IP range 192.168.1.*\n"; 687 688 #define INITIATOR_GROUP_TMPL \ 689 "[InitiatorGroup%d]\n" \ 690 " Comment \"Initiator Group%d\"\n" 691 692 #define INITIATOR_TMPL \ 693 " InitiatorName " 694 695 #define NETMASK_TMPL \ 696 " Netmask " 697 698 void 699 iscsi_init_grps_config_text(FILE *fp) 700 { 701 struct spdk_iscsi_init_grp *ig; 702 struct spdk_iscsi_initiator_name *iname; 703 struct spdk_iscsi_initiator_netmask *imask; 704 705 /* Create initiator group section */ 706 fprintf(fp, "%s", initiator_group_section); 707 708 /* Dump initiator groups */ 709 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 710 if (NULL == ig) { continue; } 711 fprintf(fp, INITIATOR_GROUP_TMPL, ig->tag, ig->tag); 712 713 /* Dump initiators */ 714 fprintf(fp, INITIATOR_TMPL); 715 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 716 fprintf(fp, "%s ", iname->name); 717 } 718 fprintf(fp, "\n"); 719 720 /* Dump netmasks */ 721 fprintf(fp, NETMASK_TMPL); 722 TAILQ_FOREACH(imask, &ig->netmask_head, tailq) { 723 fprintf(fp, "%s ", imask->mask); 724 } 725 fprintf(fp, "\n"); 726 } 727 } 728 729 static void 730 iscsi_init_grp_info_json(struct spdk_iscsi_init_grp *ig, 731 struct spdk_json_write_ctx *w) 732 { 733 struct spdk_iscsi_initiator_name *iname; 734 struct spdk_iscsi_initiator_netmask *imask; 735 736 spdk_json_write_object_begin(w); 737 738 spdk_json_write_named_int32(w, "tag", ig->tag); 739 740 spdk_json_write_named_array_begin(w, "initiators"); 741 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 742 spdk_json_write_string(w, iname->name); 743 } 744 spdk_json_write_array_end(w); 745 746 spdk_json_write_named_array_begin(w, "netmasks"); 747 TAILQ_FOREACH(imask, &ig->netmask_head, tailq) { 748 spdk_json_write_string(w, imask->mask); 749 } 750 spdk_json_write_array_end(w); 751 752 spdk_json_write_object_end(w); 753 } 754 755 static void 756 iscsi_init_grp_config_json(struct spdk_iscsi_init_grp *ig, 757 struct spdk_json_write_ctx *w) 758 { 759 spdk_json_write_object_begin(w); 760 761 spdk_json_write_named_string(w, "method", "iscsi_create_initiator_group"); 762 763 spdk_json_write_name(w, "params"); 764 iscsi_init_grp_info_json(ig, w); 765 766 spdk_json_write_object_end(w); 767 } 768 769 void 770 iscsi_init_grps_info_json(struct spdk_json_write_ctx *w) 771 { 772 struct spdk_iscsi_init_grp *ig; 773 774 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 775 iscsi_init_grp_info_json(ig, w); 776 } 777 } 778 779 void 780 iscsi_init_grps_config_json(struct spdk_json_write_ctx *w) 781 { 782 struct spdk_iscsi_init_grp *ig; 783 784 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 785 iscsi_init_grp_config_json(ig, w); 786 } 787 } 788