1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 3 * Copyright (C) 2016 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 9 #include "spdk/string.h" 10 11 #include "spdk/log.h" 12 13 #include "iscsi/iscsi.h" 14 #include "iscsi/init_grp.h" 15 16 static struct spdk_iscsi_init_grp * 17 iscsi_init_grp_create(int tag) 18 { 19 struct spdk_iscsi_init_grp *ig; 20 21 ig = calloc(1, sizeof(*ig)); 22 if (ig == NULL) { 23 SPDK_ERRLOG("calloc() failed for initiator group\n"); 24 return NULL; 25 } 26 27 ig->tag = tag; 28 TAILQ_INIT(&ig->initiator_head); 29 TAILQ_INIT(&ig->netmask_head); 30 return ig; 31 } 32 33 static struct spdk_iscsi_initiator_name * 34 iscsi_init_grp_find_initiator(struct spdk_iscsi_init_grp *ig, char *name) 35 { 36 struct spdk_iscsi_initiator_name *iname; 37 38 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 39 if (!strcmp(iname->name, name)) { 40 return iname; 41 } 42 } 43 return NULL; 44 } 45 46 static int 47 iscsi_init_grp_add_initiator(struct spdk_iscsi_init_grp *ig, char *name) 48 { 49 struct spdk_iscsi_initiator_name *iname; 50 char *p; 51 size_t len; 52 53 if (ig->ninitiators >= MAX_INITIATOR) { 54 SPDK_ERRLOG("> MAX_INITIATOR(=%d) is not allowed\n", MAX_INITIATOR); 55 return -EPERM; 56 } 57 58 len = strlen(name); 59 if (len > MAX_INITIATOR_NAME) { 60 SPDK_ERRLOG("Initiator Name is larger than 223 bytes\n"); 61 return -EINVAL; 62 } 63 64 iname = iscsi_init_grp_find_initiator(ig, name); 65 if (iname != NULL) { 66 return -EEXIST; 67 } 68 69 iname = calloc(1, sizeof(*iname)); 70 if (iname == NULL) { 71 SPDK_ERRLOG("malloc() failed for initiator name str\n"); 72 return -ENOMEM; 73 } 74 75 memcpy(iname->name, name, len); 76 77 /* Replace "ALL" by "ANY" if set */ 78 p = strstr(iname->name, "ALL"); 79 if (p != NULL) { 80 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL"); 81 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY"); 82 memcpy(p, "ANY", 3); 83 } 84 85 TAILQ_INSERT_TAIL(&ig->initiator_head, iname, tailq); 86 ig->ninitiators++; 87 88 SPDK_DEBUGLOG(iscsi, "InitiatorName %s\n", name); 89 return 0; 90 } 91 92 static int 93 iscsi_init_grp_delete_initiator(struct spdk_iscsi_init_grp *ig, char *name) 94 { 95 struct spdk_iscsi_initiator_name *iname; 96 97 iname = iscsi_init_grp_find_initiator(ig, name); 98 if (iname == NULL) { 99 return -ENOENT; 100 } 101 102 TAILQ_REMOVE(&ig->initiator_head, iname, tailq); 103 ig->ninitiators--; 104 free(iname); 105 return 0; 106 } 107 108 static int 109 iscsi_init_grp_add_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, 110 char **inames) 111 { 112 int i; 113 int rc; 114 115 for (i = 0; i < num_inames; i++) { 116 rc = iscsi_init_grp_add_initiator(ig, inames[i]); 117 if (rc < 0) { 118 goto cleanup; 119 } 120 } 121 return 0; 122 123 cleanup: 124 for (; i > 0; --i) { 125 iscsi_init_grp_delete_initiator(ig, inames[i - 1]); 126 } 127 return rc; 128 } 129 130 static void 131 iscsi_init_grp_delete_all_initiators(struct spdk_iscsi_init_grp *ig) 132 { 133 struct spdk_iscsi_initiator_name *iname, *tmp; 134 135 TAILQ_FOREACH_SAFE(iname, &ig->initiator_head, tailq, tmp) { 136 TAILQ_REMOVE(&ig->initiator_head, iname, tailq); 137 ig->ninitiators--; 138 free(iname); 139 } 140 } 141 142 static int 143 iscsi_init_grp_delete_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, char **inames) 144 { 145 int i; 146 int rc; 147 148 for (i = 0; i < num_inames; i++) { 149 rc = iscsi_init_grp_delete_initiator(ig, inames[i]); 150 if (rc < 0) { 151 goto cleanup; 152 } 153 } 154 return 0; 155 156 cleanup: 157 for (; i > 0; --i) { 158 rc = iscsi_init_grp_add_initiator(ig, inames[i - 1]); 159 if (rc != 0) { 160 iscsi_init_grp_delete_all_initiators(ig); 161 break; 162 } 163 } 164 return -1; 165 } 166 167 static struct spdk_iscsi_initiator_netmask * 168 iscsi_init_grp_find_netmask(struct spdk_iscsi_init_grp *ig, const char *mask) 169 { 170 struct spdk_iscsi_initiator_netmask *netmask; 171 172 TAILQ_FOREACH(netmask, &ig->netmask_head, tailq) { 173 if (!strcmp(netmask->mask, mask)) { 174 return netmask; 175 } 176 } 177 return NULL; 178 } 179 180 static int 181 iscsi_init_grp_add_netmask(struct spdk_iscsi_init_grp *ig, char *mask) 182 { 183 struct spdk_iscsi_initiator_netmask *imask; 184 char *p; 185 size_t len; 186 187 if (ig->nnetmasks >= MAX_NETMASK) { 188 SPDK_ERRLOG("> MAX_NETMASK(=%d) is not allowed\n", MAX_NETMASK); 189 return -EPERM; 190 } 191 192 len = strlen(mask); 193 if (len > MAX_INITIATOR_ADDR) { 194 SPDK_ERRLOG("Initiator Name is larger than %d bytes\n", MAX_INITIATOR_ADDR); 195 return -EINVAL; 196 } 197 198 imask = iscsi_init_grp_find_netmask(ig, mask); 199 if (imask != NULL) { 200 return -EEXIST; 201 } 202 203 imask = calloc(1, sizeof(*imask)); 204 if (imask == NULL) { 205 SPDK_ERRLOG("malloc() failed for initiator mask str\n"); 206 return -ENOMEM; 207 } 208 209 memcpy(imask->mask, mask, len); 210 211 /* Replace "ALL" by "ANY" if set */ 212 p = strstr(imask->mask, "ALL"); 213 if (p != NULL) { 214 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL"); 215 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY"); 216 memcpy(p, "ANY", 3); 217 } 218 219 TAILQ_INSERT_TAIL(&ig->netmask_head, imask, tailq); 220 ig->nnetmasks++; 221 222 SPDK_DEBUGLOG(iscsi, "Netmask %s\n", mask); 223 return 0; 224 } 225 226 static int 227 iscsi_init_grp_delete_netmask(struct spdk_iscsi_init_grp *ig, char *mask) 228 { 229 struct spdk_iscsi_initiator_netmask *imask; 230 231 imask = iscsi_init_grp_find_netmask(ig, mask); 232 if (imask == NULL) { 233 return -ENOENT; 234 } 235 236 TAILQ_REMOVE(&ig->netmask_head, imask, tailq); 237 ig->nnetmasks--; 238 free(imask); 239 return 0; 240 } 241 242 static int 243 iscsi_init_grp_add_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks) 244 { 245 int i; 246 int rc; 247 248 for (i = 0; i < num_imasks; i++) { 249 rc = iscsi_init_grp_add_netmask(ig, imasks[i]); 250 if (rc != 0) { 251 goto cleanup; 252 } 253 } 254 return 0; 255 256 cleanup: 257 for (; i > 0; --i) { 258 iscsi_init_grp_delete_netmask(ig, imasks[i - 1]); 259 } 260 return rc; 261 } 262 263 static void 264 iscsi_init_grp_delete_all_netmasks(struct spdk_iscsi_init_grp *ig) 265 { 266 struct spdk_iscsi_initiator_netmask *imask, *tmp; 267 268 TAILQ_FOREACH_SAFE(imask, &ig->netmask_head, tailq, tmp) { 269 TAILQ_REMOVE(&ig->netmask_head, imask, tailq); 270 ig->nnetmasks--; 271 free(imask); 272 } 273 } 274 275 static int 276 iscsi_init_grp_delete_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks) 277 { 278 int i; 279 int rc; 280 281 for (i = 0; i < num_imasks; i++) { 282 rc = iscsi_init_grp_delete_netmask(ig, imasks[i]); 283 if (rc != 0) { 284 goto cleanup; 285 } 286 } 287 return 0; 288 289 cleanup: 290 for (; i > 0; --i) { 291 rc = iscsi_init_grp_add_netmask(ig, imasks[i - 1]); 292 if (rc != 0) { 293 iscsi_init_grp_delete_all_netmasks(ig); 294 break; 295 } 296 } 297 return -1; 298 } 299 300 int 301 iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig) 302 { 303 struct spdk_iscsi_init_grp *tmp; 304 int rc = -1; 305 306 assert(ig != NULL); 307 308 pthread_mutex_lock(&g_iscsi.mutex); 309 tmp = iscsi_init_grp_find_by_tag(ig->tag); 310 if (tmp == NULL) { 311 TAILQ_INSERT_TAIL(&g_iscsi.ig_head, ig, tailq); 312 rc = 0; 313 } 314 pthread_mutex_unlock(&g_iscsi.mutex); 315 316 return rc; 317 } 318 319 /* 320 * Create initiator group from list of initiator ip/hostnames and netmasks 321 * The initiator hostname/netmask lists are allocated by the caller on the 322 * heap. Freed later by common initiator_group_destroy() code 323 */ 324 int 325 iscsi_init_grp_create_from_initiator_list(int tag, 326 int num_initiator_names, 327 char **initiator_names, 328 int num_initiator_masks, 329 char **initiator_masks) 330 { 331 int rc = -1; 332 struct spdk_iscsi_init_grp *ig = NULL; 333 334 SPDK_DEBUGLOG(iscsi, 335 "add initiator group (from initiator list) tag=%d, #initiators=%d, #masks=%d\n", 336 tag, num_initiator_names, num_initiator_masks); 337 338 ig = iscsi_init_grp_create(tag); 339 if (!ig) { 340 SPDK_ERRLOG("initiator group create error (%d)\n", tag); 341 return rc; 342 } 343 344 rc = iscsi_init_grp_add_initiators(ig, num_initiator_names, 345 initiator_names); 346 if (rc < 0) { 347 SPDK_ERRLOG("add initiator name error\n"); 348 goto cleanup; 349 } 350 351 rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks, 352 initiator_masks); 353 if (rc < 0) { 354 SPDK_ERRLOG("add initiator netmask error\n"); 355 goto cleanup; 356 } 357 358 rc = iscsi_init_grp_register(ig); 359 if (rc < 0) { 360 SPDK_ERRLOG("initiator group register error (%d)\n", tag); 361 goto cleanup; 362 } 363 return 0; 364 365 cleanup: 366 iscsi_init_grp_destroy(ig); 367 return rc; 368 } 369 370 int 371 iscsi_init_grp_add_initiators_from_initiator_list(int tag, 372 int num_initiator_names, 373 char **initiator_names, 374 int num_initiator_masks, 375 char **initiator_masks) 376 { 377 int rc = -1; 378 struct spdk_iscsi_init_grp *ig; 379 380 SPDK_DEBUGLOG(iscsi, 381 "add initiator to initiator group: tag=%d, #initiators=%d, #masks=%d\n", 382 tag, num_initiator_names, num_initiator_masks); 383 384 pthread_mutex_lock(&g_iscsi.mutex); 385 ig = iscsi_init_grp_find_by_tag(tag); 386 if (!ig) { 387 pthread_mutex_unlock(&g_iscsi.mutex); 388 SPDK_ERRLOG("initiator group (%d) is not found\n", tag); 389 return rc; 390 } 391 392 rc = iscsi_init_grp_add_initiators(ig, num_initiator_names, 393 initiator_names); 394 if (rc < 0) { 395 SPDK_ERRLOG("add initiator name error\n"); 396 goto error; 397 } 398 399 rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks, 400 initiator_masks); 401 if (rc < 0) { 402 SPDK_ERRLOG("add initiator netmask error\n"); 403 iscsi_init_grp_delete_initiators(ig, num_initiator_names, 404 initiator_names); 405 } 406 407 error: 408 pthread_mutex_unlock(&g_iscsi.mutex); 409 return rc; 410 } 411 412 int 413 iscsi_init_grp_delete_initiators_from_initiator_list(int tag, 414 int num_initiator_names, 415 char **initiator_names, 416 int num_initiator_masks, 417 char **initiator_masks) 418 { 419 int rc = -1; 420 struct spdk_iscsi_init_grp *ig; 421 422 SPDK_DEBUGLOG(iscsi, 423 "delete initiator from initiator group: tag=%d, #initiators=%d, #masks=%d\n", 424 tag, num_initiator_names, num_initiator_masks); 425 426 pthread_mutex_lock(&g_iscsi.mutex); 427 ig = iscsi_init_grp_find_by_tag(tag); 428 if (!ig) { 429 pthread_mutex_unlock(&g_iscsi.mutex); 430 SPDK_ERRLOG("initiator group (%d) is not found\n", tag); 431 return rc; 432 } 433 434 rc = iscsi_init_grp_delete_initiators(ig, num_initiator_names, 435 initiator_names); 436 if (rc < 0) { 437 SPDK_ERRLOG("delete initiator name error\n"); 438 goto error; 439 } 440 441 rc = iscsi_init_grp_delete_netmasks(ig, num_initiator_masks, 442 initiator_masks); 443 if (rc < 0) { 444 SPDK_ERRLOG("delete initiator netmask error\n"); 445 iscsi_init_grp_add_initiators(ig, num_initiator_names, 446 initiator_names); 447 goto error; 448 } 449 450 error: 451 pthread_mutex_unlock(&g_iscsi.mutex); 452 return rc; 453 } 454 455 void 456 iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig) 457 { 458 if (!ig) { 459 return; 460 } 461 462 iscsi_init_grp_delete_all_initiators(ig); 463 iscsi_init_grp_delete_all_netmasks(ig); 464 free(ig); 465 }; 466 467 struct spdk_iscsi_init_grp * 468 iscsi_init_grp_find_by_tag(int tag) 469 { 470 struct spdk_iscsi_init_grp *ig; 471 472 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 473 if (ig->tag == tag) { 474 return ig; 475 } 476 } 477 478 return NULL; 479 } 480 481 void 482 iscsi_init_grps_destroy(void) 483 { 484 struct spdk_iscsi_init_grp *ig, *tmp; 485 486 SPDK_DEBUGLOG(iscsi, "iscsi_init_grp_array_destroy\n"); 487 pthread_mutex_lock(&g_iscsi.mutex); 488 TAILQ_FOREACH_SAFE(ig, &g_iscsi.ig_head, tailq, tmp) { 489 TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq); 490 iscsi_init_grp_destroy(ig); 491 } 492 pthread_mutex_unlock(&g_iscsi.mutex); 493 } 494 495 struct spdk_iscsi_init_grp * 496 iscsi_init_grp_unregister(int tag) 497 { 498 struct spdk_iscsi_init_grp *ig; 499 500 pthread_mutex_lock(&g_iscsi.mutex); 501 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 502 if (ig->tag == tag) { 503 TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq); 504 pthread_mutex_unlock(&g_iscsi.mutex); 505 return ig; 506 } 507 } 508 pthread_mutex_unlock(&g_iscsi.mutex); 509 return NULL; 510 } 511 512 static void 513 iscsi_init_grp_info_json(struct spdk_iscsi_init_grp *ig, 514 struct spdk_json_write_ctx *w) 515 { 516 struct spdk_iscsi_initiator_name *iname; 517 struct spdk_iscsi_initiator_netmask *imask; 518 519 spdk_json_write_object_begin(w); 520 521 spdk_json_write_named_int32(w, "tag", ig->tag); 522 523 spdk_json_write_named_array_begin(w, "initiators"); 524 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 525 spdk_json_write_string(w, iname->name); 526 } 527 spdk_json_write_array_end(w); 528 529 spdk_json_write_named_array_begin(w, "netmasks"); 530 TAILQ_FOREACH(imask, &ig->netmask_head, tailq) { 531 spdk_json_write_string(w, imask->mask); 532 } 533 spdk_json_write_array_end(w); 534 535 spdk_json_write_object_end(w); 536 } 537 538 static void 539 iscsi_init_grp_config_json(struct spdk_iscsi_init_grp *ig, 540 struct spdk_json_write_ctx *w) 541 { 542 spdk_json_write_object_begin(w); 543 544 spdk_json_write_named_string(w, "method", "iscsi_create_initiator_group"); 545 546 spdk_json_write_name(w, "params"); 547 iscsi_init_grp_info_json(ig, w); 548 549 spdk_json_write_object_end(w); 550 } 551 552 void 553 iscsi_init_grps_info_json(struct spdk_json_write_ctx *w) 554 { 555 struct spdk_iscsi_init_grp *ig; 556 557 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 558 iscsi_init_grp_info_json(ig, w); 559 } 560 } 561 562 void 563 iscsi_init_grps_config_json(struct spdk_json_write_ctx *w) 564 { 565 struct spdk_iscsi_init_grp *ig; 566 567 TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) { 568 iscsi_init_grp_config_json(ig, w); 569 } 570 } 571