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