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 "iscsi/iscsi.h" 36 #include "iscsi/conn.h" 37 #include "iscsi/tgt_node.h" 38 #include "iscsi/portal_grp.h" 39 #include "iscsi/init_grp.h" 40 41 #include "spdk/rpc.h" 42 #include "spdk/util.h" 43 #include "spdk/event.h" 44 #include "spdk/string.h" 45 #include "spdk_internal/log.h" 46 47 static void 48 spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_request *request, 49 const struct spdk_json_val *params) 50 { 51 struct spdk_json_write_ctx *w; 52 53 if (params != NULL) { 54 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 55 "get_initiator_groups requires no parameters"); 56 return; 57 } 58 59 w = spdk_jsonrpc_begin_result(request); 60 if (w == NULL) { 61 return; 62 } 63 64 spdk_json_write_array_begin(w); 65 spdk_iscsi_init_grps_info_json(w); 66 spdk_json_write_array_end(w); 67 68 spdk_jsonrpc_end_result(request, w); 69 } 70 SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups, SPDK_RPC_RUNTIME) 71 72 struct rpc_initiator_list { 73 size_t num_initiators; 74 char *initiators[MAX_INITIATOR]; 75 }; 76 77 static int 78 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 79 { 80 struct rpc_initiator_list *list = out; 81 82 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 83 &list->num_initiators, sizeof(char *)); 84 } 85 86 static void 87 free_rpc_initiator_list(struct rpc_initiator_list *list) 88 { 89 size_t i; 90 91 for (i = 0; i < list->num_initiators; i++) { 92 free(list->initiators[i]); 93 } 94 } 95 96 struct rpc_netmask_list { 97 size_t num_netmasks; 98 char *netmasks[MAX_NETMASK]; 99 }; 100 101 static int 102 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 103 { 104 struct rpc_netmask_list *list = out; 105 106 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 107 &list->num_netmasks, sizeof(char *)); 108 } 109 110 static void 111 free_rpc_netmask_list(struct rpc_netmask_list *list) 112 { 113 size_t i; 114 115 for (i = 0; i < list->num_netmasks; i++) { 116 free(list->netmasks[i]); 117 } 118 } 119 120 struct rpc_initiator_group { 121 int32_t tag; 122 struct rpc_initiator_list initiator_list; 123 struct rpc_netmask_list netmask_list; 124 }; 125 126 static void 127 free_rpc_initiator_group(struct rpc_initiator_group *ig) 128 { 129 free_rpc_initiator_list(&ig->initiator_list); 130 free_rpc_netmask_list(&ig->netmask_list); 131 } 132 133 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 134 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 135 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 136 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 137 }; 138 139 static void 140 spdk_rpc_add_initiator_group(struct spdk_jsonrpc_request *request, 141 const struct spdk_json_val *params) 142 { 143 struct rpc_initiator_group req = {}; 144 struct spdk_json_write_ctx *w; 145 146 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 147 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 148 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 149 goto invalid; 150 } 151 152 if (req.initiator_list.num_initiators == 0 || 153 req.netmask_list.num_netmasks == 0) { 154 goto invalid; 155 } 156 157 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 158 req.initiator_list.num_initiators, 159 req.initiator_list.initiators, 160 req.netmask_list.num_netmasks, 161 req.netmask_list.netmasks)) { 162 SPDK_ERRLOG("create_from_initiator_list failed\n"); 163 goto invalid; 164 } 165 166 free_rpc_initiator_group(&req); 167 168 w = spdk_jsonrpc_begin_result(request); 169 if (w == NULL) { 170 return; 171 } 172 173 spdk_json_write_bool(w, true); 174 spdk_jsonrpc_end_result(request, w); 175 return; 176 177 invalid: 178 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 179 free_rpc_initiator_group(&req); 180 } 181 SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group, SPDK_RPC_RUNTIME) 182 183 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 184 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 185 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 186 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 187 }; 188 189 static void 190 spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request, 191 const struct spdk_json_val *params) 192 { 193 struct rpc_initiator_group req = {}; 194 struct spdk_json_write_ctx *w; 195 196 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 197 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 198 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 199 goto invalid; 200 } 201 202 if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 203 req.initiator_list.num_initiators, 204 req.initiator_list.initiators, 205 req.netmask_list.num_netmasks, 206 req.netmask_list.netmasks)) { 207 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 208 goto invalid; 209 } 210 211 free_rpc_initiator_group(&req); 212 213 w = spdk_jsonrpc_begin_result(request); 214 if (w == NULL) { 215 return; 216 } 217 218 spdk_json_write_bool(w, true); 219 spdk_jsonrpc_end_result(request, w); 220 return; 221 222 invalid: 223 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 224 free_rpc_initiator_group(&req); 225 } 226 SPDK_RPC_REGISTER("add_initiators_to_initiator_group", 227 spdk_rpc_add_initiators_to_initiator_group, SPDK_RPC_RUNTIME) 228 229 static void 230 spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request, 231 const struct spdk_json_val *params) 232 { 233 struct rpc_initiator_group req = {}; 234 struct spdk_json_write_ctx *w; 235 236 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 237 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 238 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 239 goto invalid; 240 } 241 242 if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 243 req.initiator_list.num_initiators, 244 req.initiator_list.initiators, 245 req.netmask_list.num_netmasks, 246 req.netmask_list.netmasks)) { 247 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 248 goto invalid; 249 } 250 251 free_rpc_initiator_group(&req); 252 253 w = spdk_jsonrpc_begin_result(request); 254 if (w == NULL) { 255 return; 256 } 257 258 spdk_json_write_bool(w, true); 259 spdk_jsonrpc_end_result(request, w); 260 return; 261 262 invalid: 263 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 264 free_rpc_initiator_group(&req); 265 } 266 SPDK_RPC_REGISTER("delete_initiators_from_initiator_group", 267 spdk_rpc_delete_initiators_from_initiator_group, SPDK_RPC_RUNTIME) 268 269 struct rpc_delete_initiator_group { 270 int32_t tag; 271 }; 272 273 static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = { 274 {"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32}, 275 }; 276 277 static void 278 spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_request *request, 279 const struct spdk_json_val *params) 280 { 281 struct rpc_delete_initiator_group req = {}; 282 struct spdk_json_write_ctx *w; 283 struct spdk_iscsi_init_grp *ig; 284 285 if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders, 286 SPDK_COUNTOF(rpc_delete_initiator_group_decoders), 287 &req)) { 288 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 289 goto invalid; 290 } 291 292 ig = spdk_iscsi_init_grp_unregister(req.tag); 293 if (!ig) { 294 goto invalid; 295 } 296 spdk_iscsi_tgt_node_delete_map(NULL, ig); 297 spdk_iscsi_init_grp_destroy(ig); 298 299 w = spdk_jsonrpc_begin_result(request); 300 if (w == NULL) { 301 return; 302 } 303 304 spdk_json_write_bool(w, true); 305 spdk_jsonrpc_end_result(request, w); 306 return; 307 308 invalid: 309 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 310 } 311 SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group, SPDK_RPC_RUNTIME) 312 313 static void 314 spdk_rpc_get_target_nodes(struct spdk_jsonrpc_request *request, 315 const struct spdk_json_val *params) 316 { 317 struct spdk_json_write_ctx *w; 318 319 if (params != NULL) { 320 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 321 "get_target_nodes requires no parameters"); 322 return; 323 } 324 325 w = spdk_jsonrpc_begin_result(request); 326 if (w == NULL) { 327 return; 328 } 329 330 spdk_json_write_array_begin(w); 331 spdk_iscsi_tgt_nodes_info_json(w); 332 spdk_json_write_array_end(w); 333 334 spdk_jsonrpc_end_result(request, w); 335 } 336 SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes, SPDK_RPC_RUNTIME) 337 338 struct rpc_pg_ig_map { 339 int32_t pg_tag; 340 int32_t ig_tag; 341 }; 342 343 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 344 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 345 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 346 }; 347 348 static int 349 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 350 { 351 struct rpc_pg_ig_map *pg_ig_map = out; 352 353 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 354 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 355 pg_ig_map); 356 } 357 358 struct rpc_pg_ig_maps { 359 size_t num_maps; 360 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 361 }; 362 363 static int 364 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 365 { 366 struct rpc_pg_ig_maps *pg_ig_maps = out; 367 368 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 369 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 370 sizeof(struct rpc_pg_ig_map)); 371 } 372 373 #define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64 374 375 struct rpc_lun { 376 char *bdev_name; 377 int32_t lun_id; 378 }; 379 380 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 381 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 382 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 383 }; 384 385 static int 386 decode_rpc_lun(const struct spdk_json_val *val, void *out) 387 { 388 struct rpc_lun *lun = out; 389 390 return spdk_json_decode_object(val, rpc_lun_decoders, 391 SPDK_COUNTOF(rpc_lun_decoders), lun); 392 } 393 394 struct rpc_luns { 395 size_t num_luns; 396 struct rpc_lun luns[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 397 }; 398 399 static int 400 decode_rpc_luns(const struct spdk_json_val *val, void *out) 401 { 402 struct rpc_luns *luns = out; 403 404 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 405 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 406 &luns->num_luns, sizeof(struct rpc_lun)); 407 } 408 409 static void 410 free_rpc_luns(struct rpc_luns *p) 411 { 412 size_t i; 413 414 for (i = 0; i < p->num_luns; i++) { 415 free(p->luns[i].bdev_name); 416 } 417 } 418 419 struct rpc_target_node { 420 char *name; 421 char *alias_name; 422 423 struct rpc_pg_ig_maps pg_ig_maps; 424 struct rpc_luns luns; 425 426 int32_t queue_depth; 427 bool disable_chap; 428 bool require_chap; 429 bool mutual_chap; 430 int32_t chap_group; 431 432 bool header_digest; 433 bool data_digest; 434 }; 435 436 static void 437 free_rpc_target_node(struct rpc_target_node *req) 438 { 439 free(req->name); 440 free(req->alias_name); 441 free_rpc_luns(&req->luns); 442 } 443 444 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 445 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 446 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 447 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 448 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 449 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 450 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 451 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 452 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 453 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 454 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 455 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 456 }; 457 458 static void 459 spdk_rpc_construct_target_node(struct spdk_jsonrpc_request *request, 460 const struct spdk_json_val *params) 461 { 462 struct rpc_target_node req = {}; 463 struct spdk_json_write_ctx *w; 464 struct spdk_iscsi_tgt_node *target; 465 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 466 char *bdev_names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 467 int32_t lun_ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 468 size_t i; 469 470 if (spdk_json_decode_object(params, rpc_target_node_decoders, 471 SPDK_COUNTOF(rpc_target_node_decoders), 472 &req)) { 473 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 474 goto invalid; 475 } 476 477 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 478 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 479 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 480 } 481 482 for (i = 0; i < req.luns.num_luns; i++) { 483 bdev_names[i] = req.luns.luns[i].bdev_name; 484 lun_ids[i] = req.luns.luns[i].lun_id; 485 } 486 487 /* 488 * Use default parameters in a few places: 489 * index = -1 : automatically pick an index for the new target node 490 * alias = NULL 491 */ 492 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 493 pg_tags, 494 ig_tags, 495 req.pg_ig_maps.num_maps, 496 (const char **)bdev_names, 497 lun_ids, 498 req.luns.num_luns, 499 req.queue_depth, 500 req.disable_chap, 501 req.require_chap, 502 req.mutual_chap, 503 req.chap_group, 504 req.header_digest, 505 req.data_digest); 506 507 if (target == NULL) { 508 goto invalid; 509 } 510 511 free_rpc_target_node(&req); 512 513 w = spdk_jsonrpc_begin_result(request); 514 if (w == NULL) { 515 return; 516 } 517 518 spdk_json_write_bool(w, true); 519 spdk_jsonrpc_end_result(request, w); 520 return; 521 522 invalid: 523 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 524 free_rpc_target_node(&req); 525 } 526 SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node, SPDK_RPC_RUNTIME) 527 528 struct rpc_tgt_node_pg_ig_maps { 529 char *name; 530 struct rpc_pg_ig_maps pg_ig_maps; 531 }; 532 533 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 534 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 535 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 536 }; 537 538 static void 539 spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 540 const struct spdk_json_val *params) 541 { 542 struct rpc_tgt_node_pg_ig_maps req = {}; 543 struct spdk_json_write_ctx *w; 544 struct spdk_iscsi_tgt_node *target; 545 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 546 size_t i; 547 int rc; 548 549 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 550 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 551 &req)) { 552 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 553 goto invalid; 554 } 555 556 target = spdk_iscsi_find_tgt_node(req.name); 557 if (target == NULL) { 558 SPDK_ERRLOG("target is not found\n"); 559 goto invalid; 560 } 561 562 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 563 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 564 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 565 } 566 567 rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, pg_tags, ig_tags, 568 req.pg_ig_maps.num_maps); 569 if (rc < 0) { 570 SPDK_ERRLOG("add pg-ig maps failed\n"); 571 goto invalid; 572 } 573 574 free(req.name); 575 576 w = spdk_jsonrpc_begin_result(request); 577 if (w != NULL) { 578 spdk_json_write_bool(w, true); 579 spdk_jsonrpc_end_result(request, w); 580 } 581 return; 582 583 invalid: 584 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 585 "Invalid parameters"); 586 free(req.name); 587 } 588 SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps, SPDK_RPC_RUNTIME) 589 590 static void 591 spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request, 592 const struct spdk_json_val *params) 593 { 594 struct rpc_tgt_node_pg_ig_maps req = {}; 595 struct spdk_json_write_ctx *w; 596 struct spdk_iscsi_tgt_node *target; 597 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 598 size_t i; 599 int rc; 600 601 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 602 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 603 &req)) { 604 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 605 goto invalid; 606 } 607 608 target = spdk_iscsi_find_tgt_node(req.name); 609 if (target == NULL) { 610 SPDK_ERRLOG("target is not found\n"); 611 goto invalid; 612 } 613 614 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 615 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 616 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 617 } 618 619 rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, pg_tags, ig_tags, 620 req.pg_ig_maps.num_maps); 621 if (rc < 0) { 622 SPDK_ERRLOG("remove pg-ig maps failed\n"); 623 goto invalid; 624 } 625 626 free(req.name); 627 628 w = spdk_jsonrpc_begin_result(request); 629 if (w != NULL) { 630 spdk_json_write_bool(w, true); 631 spdk_jsonrpc_end_result(request, w); 632 } 633 return; 634 635 invalid: 636 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 637 "Invalid parameters"); 638 free(req.name); 639 } 640 SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps, SPDK_RPC_RUNTIME) 641 642 struct rpc_delete_target_node { 643 char *name; 644 }; 645 646 static void 647 free_rpc_delete_target_node(struct rpc_delete_target_node *r) 648 { 649 free(r->name); 650 } 651 652 static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = { 653 {"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string}, 654 }; 655 656 static void 657 spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request, 658 const struct spdk_json_val *params) 659 { 660 struct rpc_delete_target_node req = {}; 661 struct spdk_json_write_ctx *w; 662 663 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 664 SPDK_COUNTOF(rpc_delete_target_node_decoders), 665 &req)) { 666 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 667 goto invalid; 668 } 669 670 if (req.name == NULL) { 671 SPDK_ERRLOG("missing name param\n"); 672 goto invalid; 673 } 674 675 if (spdk_iscsi_shutdown_tgt_node_by_name(req.name)) { 676 SPDK_ERRLOG("shutdown_tgt_node_by_name failed\n"); 677 goto invalid; 678 } 679 680 free_rpc_delete_target_node(&req); 681 682 w = spdk_jsonrpc_begin_result(request); 683 if (w == NULL) { 684 return; 685 } 686 687 spdk_json_write_bool(w, true); 688 spdk_jsonrpc_end_result(request, w); 689 return; 690 691 invalid: 692 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 693 free_rpc_delete_target_node(&req); 694 } 695 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node, SPDK_RPC_RUNTIME) 696 697 static void 698 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request, 699 const struct spdk_json_val *params) 700 { 701 struct spdk_json_write_ctx *w; 702 703 if (params != NULL) { 704 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 705 "get_portal_groups requires no parameters"); 706 return; 707 } 708 709 w = spdk_jsonrpc_begin_result(request); 710 if (w == NULL) { 711 return; 712 } 713 714 spdk_json_write_array_begin(w); 715 spdk_iscsi_portal_grps_info_json(w); 716 spdk_json_write_array_end(w); 717 718 spdk_jsonrpc_end_result(request, w); 719 } 720 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups, SPDK_RPC_RUNTIME) 721 722 struct rpc_portal { 723 char *host; 724 char *port; 725 char *cpumask; 726 }; 727 728 struct rpc_portal_list { 729 size_t num_portals; 730 struct rpc_portal portals[MAX_PORTAL]; 731 }; 732 733 struct rpc_portal_group { 734 int32_t tag; 735 struct rpc_portal_list portal_list; 736 }; 737 738 static void 739 free_rpc_portal(struct rpc_portal *portal) 740 { 741 free(portal->host); 742 free(portal->port); 743 free(portal->cpumask); 744 } 745 746 static void 747 free_rpc_portal_list(struct rpc_portal_list *pl) 748 { 749 size_t i; 750 751 for (i = 0; i < pl->num_portals; i++) { 752 free_rpc_portal(&pl->portals[i]); 753 } 754 pl->num_portals = 0; 755 } 756 757 static void 758 free_rpc_portal_group(struct rpc_portal_group *pg) 759 { 760 free_rpc_portal_list(&pg->portal_list); 761 } 762 763 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 764 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 765 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 766 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 767 }; 768 769 static int 770 decode_rpc_portal(const struct spdk_json_val *val, void *out) 771 { 772 struct rpc_portal *portal = out; 773 774 return spdk_json_decode_object(val, rpc_portal_decoders, 775 SPDK_COUNTOF(rpc_portal_decoders), 776 portal); 777 } 778 779 static int 780 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 781 { 782 struct rpc_portal_list *list = out; 783 784 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 785 sizeof(struct rpc_portal)); 786 } 787 788 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 789 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 790 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 791 }; 792 793 static void 794 spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request, 795 const struct spdk_json_val *params) 796 { 797 struct rpc_portal_group req = {}; 798 struct spdk_iscsi_portal_grp *pg = NULL; 799 struct spdk_iscsi_portal *portal; 800 struct spdk_json_write_ctx *w; 801 size_t i = 0; 802 int rc = -1; 803 804 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 805 SPDK_COUNTOF(rpc_portal_group_decoders), 806 &req)) { 807 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 808 goto out; 809 } 810 811 pg = spdk_iscsi_portal_grp_create(req.tag); 812 if (pg == NULL) { 813 SPDK_ERRLOG("portal_grp_create failed\n"); 814 goto out; 815 } 816 for (i = 0; i < req.portal_list.num_portals; i++) { 817 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 818 req.portal_list.portals[i].port, 819 req.portal_list.portals[i].cpumask); 820 if (portal == NULL) { 821 SPDK_ERRLOG("portal_create failed\n"); 822 goto out; 823 } 824 spdk_iscsi_portal_grp_add_portal(pg, portal); 825 } 826 827 rc = spdk_iscsi_portal_grp_open(pg); 828 if (rc != 0) { 829 SPDK_ERRLOG("portal_grp_open failed\n"); 830 goto out; 831 } 832 833 rc = spdk_iscsi_portal_grp_register(pg); 834 if (rc != 0) { 835 SPDK_ERRLOG("portal_grp_register failed\n"); 836 } 837 838 out: 839 if (rc == 0) { 840 w = spdk_jsonrpc_begin_result(request); 841 if (w != NULL) { 842 spdk_json_write_bool(w, true); 843 spdk_jsonrpc_end_result(request, w); 844 } 845 } else { 846 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 847 848 if (pg != NULL) { 849 spdk_iscsi_portal_grp_release(pg); 850 } 851 } 852 free_rpc_portal_group(&req); 853 } 854 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group, SPDK_RPC_RUNTIME) 855 856 struct rpc_delete_portal_group { 857 int32_t tag; 858 }; 859 860 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 861 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 862 }; 863 864 static void 865 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request, 866 const struct spdk_json_val *params) 867 { 868 struct rpc_delete_portal_group req = {}; 869 struct spdk_json_write_ctx *w; 870 struct spdk_iscsi_portal_grp *pg; 871 872 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 873 SPDK_COUNTOF(rpc_delete_portal_group_decoders), 874 &req)) { 875 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 876 goto invalid; 877 } 878 879 pg = spdk_iscsi_portal_grp_unregister(req.tag); 880 if (!pg) { 881 goto invalid; 882 } 883 884 spdk_iscsi_tgt_node_delete_map(pg, NULL); 885 spdk_iscsi_portal_grp_release(pg); 886 887 w = spdk_jsonrpc_begin_result(request); 888 if (w == NULL) { 889 return; 890 } 891 892 spdk_json_write_bool(w, true); 893 spdk_jsonrpc_end_result(request, w); 894 return; 895 896 invalid: 897 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 898 } 899 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group, SPDK_RPC_RUNTIME) 900 901 static void 902 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request, 903 const struct spdk_json_val *params) 904 { 905 struct spdk_json_write_ctx *w; 906 struct spdk_iscsi_conn *conns = g_conns_array; 907 int i; 908 uint16_t tsih; 909 910 if (params != NULL) { 911 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 912 "get_iscsi_connections requires no parameters"); 913 return; 914 } 915 916 w = spdk_jsonrpc_begin_result(request); 917 if (w == NULL) { 918 return; 919 } 920 921 spdk_json_write_array_begin(w); 922 923 for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) { 924 struct spdk_iscsi_conn *c = &conns[i]; 925 926 if (!c->is_valid) { 927 continue; 928 } 929 930 spdk_json_write_object_begin(w); 931 932 spdk_json_write_named_int32(w, "id", c->id); 933 934 spdk_json_write_named_int32(w, "cid", c->cid); 935 936 /* 937 * If we try to return data for a connection that has not 938 * logged in yet, the session will not be set. So in this 939 * case, return -1 for the tsih rather than segfaulting 940 * on the null c->sess. 941 */ 942 if (c->sess == NULL) { 943 tsih = -1; 944 } else { 945 tsih = c->sess->tsih; 946 } 947 spdk_json_write_named_int32(w, "tsih", tsih); 948 949 spdk_json_write_named_int32(w, "lcore_id", c->lcore); 950 951 spdk_json_write_named_string(w, "initiator_addr", c->initiator_addr); 952 953 spdk_json_write_named_string(w, "target_addr", c->target_addr); 954 955 spdk_json_write_named_string(w, "target_node_name", c->target_short_name); 956 957 spdk_json_write_object_end(w); 958 } 959 spdk_json_write_array_end(w); 960 961 spdk_jsonrpc_end_result(request, w); 962 } 963 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections, SPDK_RPC_RUNTIME) 964 965 struct rpc_target_lun { 966 char *name; 967 char *bdev_name; 968 int32_t lun_id; 969 }; 970 971 static void 972 free_rpc_target_lun(struct rpc_target_lun *req) 973 { 974 free(req->name); 975 free(req->bdev_name); 976 } 977 978 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 979 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 980 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 981 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 982 }; 983 984 static void 985 spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request, 986 const struct spdk_json_val *params) 987 { 988 struct rpc_target_lun req = {}; 989 struct spdk_json_write_ctx *w; 990 struct spdk_iscsi_tgt_node *target; 991 int rc; 992 993 req.lun_id = -1; 994 995 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 996 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 997 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 998 goto invalid; 999 } 1000 1001 target = spdk_iscsi_find_tgt_node(req.name); 1002 if (target == NULL) { 1003 SPDK_ERRLOG("target is not found\n"); 1004 goto invalid; 1005 } 1006 1007 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1008 if (rc < 0) { 1009 SPDK_ERRLOG("add lun failed\n"); 1010 goto invalid; 1011 } 1012 1013 free_rpc_target_lun(&req); 1014 1015 w = spdk_jsonrpc_begin_result(request); 1016 if (w == NULL) { 1017 return; 1018 } 1019 1020 spdk_json_write_bool(w, true); 1021 spdk_jsonrpc_end_result(request, w); 1022 return; 1023 1024 invalid: 1025 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1026 "Invalid parameters"); 1027 free_rpc_target_lun(&req); 1028 } 1029 SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME) 1030 1031 struct rpc_target_auth { 1032 char *name; 1033 bool disable_chap; 1034 bool require_chap; 1035 bool mutual_chap; 1036 int32_t chap_group; 1037 }; 1038 1039 static void 1040 free_rpc_target_auth(struct rpc_target_auth *req) 1041 { 1042 free(req->name); 1043 } 1044 1045 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1046 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1047 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1048 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1049 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1050 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1051 }; 1052 1053 static void 1054 spdk_rpc_set_iscsi_target_node_auth(struct spdk_jsonrpc_request *request, 1055 const struct spdk_json_val *params) 1056 { 1057 struct rpc_target_auth req = {}; 1058 struct spdk_json_write_ctx *w; 1059 struct spdk_iscsi_tgt_node *target; 1060 int rc; 1061 1062 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1063 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1064 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1065 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1066 "Invalid parameters"); 1067 goto exit; 1068 } 1069 1070 target = spdk_iscsi_find_tgt_node(req.name); 1071 if (target == NULL) { 1072 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1073 "Could not find target %s", req.name); 1074 goto exit; 1075 } 1076 1077 rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1078 req.mutual_chap, req.chap_group); 1079 if (rc < 0) { 1080 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1081 "Invalid combination of auth params"); 1082 goto exit; 1083 } 1084 1085 free_rpc_target_auth(&req); 1086 1087 w = spdk_jsonrpc_begin_result(request); 1088 if (w == NULL) { 1089 return; 1090 } 1091 1092 spdk_json_write_bool(w, true); 1093 spdk_jsonrpc_end_result(request, w); 1094 return; 1095 1096 exit: 1097 free_rpc_target_auth(&req); 1098 } 1099 SPDK_RPC_REGISTER("set_iscsi_target_node_auth", spdk_rpc_set_iscsi_target_node_auth, 1100 SPDK_RPC_RUNTIME) 1101 1102 static void 1103 spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request, 1104 const struct spdk_json_val *params) 1105 { 1106 struct spdk_json_write_ctx *w; 1107 1108 if (params != NULL) { 1109 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1110 "get_iscsi_global_params requires no parameters"); 1111 return; 1112 } 1113 1114 w = spdk_jsonrpc_begin_result(request); 1115 if (w == NULL) { 1116 return; 1117 } 1118 1119 spdk_iscsi_opts_info_json(w); 1120 1121 spdk_jsonrpc_end_result(request, w); 1122 } 1123 SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME) 1124 1125 struct rpc_discovery_auth { 1126 bool disable_chap; 1127 bool require_chap; 1128 bool mutual_chap; 1129 int32_t chap_group; 1130 }; 1131 1132 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1133 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1134 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1135 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1136 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1137 }; 1138 1139 static void 1140 spdk_rpc_set_iscsi_discovery_auth(struct spdk_jsonrpc_request *request, 1141 const struct spdk_json_val *params) 1142 { 1143 struct rpc_discovery_auth req = {}; 1144 struct spdk_json_write_ctx *w; 1145 int rc; 1146 1147 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1148 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1149 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1150 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1151 "Invalid parameters"); 1152 return; 1153 } 1154 1155 rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1156 req.mutual_chap, req.chap_group); 1157 if (rc < 0) { 1158 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1159 "Invalid combination of CHAP params"); 1160 return; 1161 } 1162 1163 w = spdk_jsonrpc_begin_result(request); 1164 if (w == NULL) { 1165 return; 1166 } 1167 1168 spdk_json_write_bool(w, true); 1169 spdk_jsonrpc_end_result(request, w); 1170 } 1171 SPDK_RPC_REGISTER("set_iscsi_discovery_auth", spdk_rpc_set_iscsi_discovery_auth, SPDK_RPC_RUNTIME) 1172 1173 1174 #define MAX_AUTH_SECRETS 64 1175 1176 struct rpc_auth_secret { 1177 char *user; 1178 char *secret; 1179 char *muser; 1180 char *msecret; 1181 }; 1182 1183 static void 1184 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1185 { 1186 free(_secret->user); 1187 free(_secret->secret); 1188 free(_secret->muser); 1189 free(_secret->msecret); 1190 } 1191 1192 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1193 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1194 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1195 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1196 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1197 }; 1198 1199 static int 1200 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1201 { 1202 struct rpc_auth_secret *_secret = out; 1203 1204 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1205 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1206 } 1207 1208 struct rpc_auth_secrets { 1209 size_t num_secret; 1210 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1211 }; 1212 1213 static void 1214 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1215 { 1216 size_t i; 1217 1218 for (i = 0; i < secrets->num_secret; i++) { 1219 free_rpc_auth_secret(&secrets->secrets[i]); 1220 } 1221 } 1222 1223 static int 1224 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1225 { 1226 struct rpc_auth_secrets *secrets = out; 1227 1228 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1229 MAX_AUTH_SECRETS, &secrets->num_secret, 1230 sizeof(struct rpc_auth_secret)); 1231 } 1232 1233 struct rpc_auth_group { 1234 int32_t tag; 1235 struct rpc_auth_secrets secrets; 1236 }; 1237 1238 static void 1239 free_rpc_auth_group(struct rpc_auth_group *group) 1240 { 1241 free_rpc_auth_secrets(&group->secrets); 1242 } 1243 1244 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1245 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1246 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1247 }; 1248 1249 static void 1250 spdk_rpc_add_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1251 const struct spdk_json_val *params) 1252 { 1253 struct rpc_auth_group req = {}; 1254 struct rpc_auth_secret *_secret; 1255 struct spdk_json_write_ctx *w; 1256 struct spdk_iscsi_auth_group *group = NULL; 1257 int rc; 1258 size_t i; 1259 1260 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1261 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1262 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1263 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1264 "Invalid parameters"); 1265 free_rpc_auth_group(&req); 1266 return; 1267 } 1268 1269 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1270 1271 rc = spdk_iscsi_add_auth_group(req.tag, &group); 1272 if (rc != 0) { 1273 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1274 1275 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1276 "Could not add auth group (%d), %s", 1277 req.tag, spdk_strerror(-rc)); 1278 free_rpc_auth_group(&req); 1279 return; 1280 } 1281 1282 for (i = 0; i < req.secrets.num_secret; i++) { 1283 _secret = &req.secrets.secrets[i]; 1284 rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1285 _secret->muser, _secret->msecret); 1286 if (rc != 0) { 1287 spdk_iscsi_delete_auth_group(group); 1288 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1289 1290 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1291 "Could not add secret to auth group (%d), %s", 1292 req.tag, spdk_strerror(-rc)); 1293 free_rpc_auth_group(&req); 1294 return; 1295 } 1296 } 1297 1298 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1299 1300 free_rpc_auth_group(&req); 1301 1302 w = spdk_jsonrpc_begin_result(request); 1303 if (w == NULL) { 1304 return; 1305 } 1306 1307 spdk_json_write_bool(w, true); 1308 spdk_jsonrpc_end_result(request, w); 1309 } 1310 SPDK_RPC_REGISTER("add_iscsi_auth_group", spdk_rpc_add_iscsi_auth_group, SPDK_RPC_RUNTIME) 1311 1312 struct rpc_delete_auth_group { 1313 int32_t tag; 1314 }; 1315 1316 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1317 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1318 }; 1319 1320 static void 1321 spdk_rpc_delete_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1322 const struct spdk_json_val *params) 1323 { 1324 struct rpc_delete_auth_group req = {}; 1325 struct spdk_json_write_ctx *w; 1326 struct spdk_iscsi_auth_group *group; 1327 1328 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1329 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1330 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1331 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1332 "Invalid parameters"); 1333 return; 1334 } 1335 1336 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1337 1338 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1339 if (group == NULL) { 1340 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1341 1342 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1343 "Could not find auth group (%d)", req.tag); 1344 return; 1345 } 1346 1347 spdk_iscsi_delete_auth_group(group); 1348 1349 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1350 1351 w = spdk_jsonrpc_begin_result(request); 1352 if (w == NULL) { 1353 return; 1354 } 1355 1356 spdk_json_write_bool(w, true); 1357 spdk_jsonrpc_end_result(request, w); 1358 } 1359 SPDK_RPC_REGISTER("delete_iscsi_auth_group", spdk_rpc_delete_iscsi_auth_group, SPDK_RPC_RUNTIME) 1360 1361 struct rpc_add_auth_secret { 1362 int32_t tag; 1363 char *user; 1364 char *secret; 1365 char *muser; 1366 char *msecret; 1367 }; 1368 1369 static void 1370 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1371 { 1372 free(_secret->user); 1373 free(_secret->secret); 1374 free(_secret->muser); 1375 free(_secret->msecret); 1376 } 1377 1378 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1379 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1380 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1381 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1382 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1383 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1384 }; 1385 1386 static void 1387 spdk_rpc_add_secret_to_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1388 const struct spdk_json_val *params) 1389 { 1390 struct rpc_add_auth_secret req = {}; 1391 struct spdk_json_write_ctx *w; 1392 struct spdk_iscsi_auth_group *group; 1393 int rc; 1394 1395 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1396 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1397 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1398 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1399 "Invalid parameters"); 1400 free_rpc_add_auth_secret(&req); 1401 return; 1402 } 1403 1404 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1405 1406 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1407 if (group == NULL) { 1408 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1409 1410 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1411 "Could not find auth group (%d)", req.tag); 1412 free_rpc_add_auth_secret(&req); 1413 return; 1414 } 1415 1416 rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1417 if (rc != 0) { 1418 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1419 1420 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1421 "Could not add secret to auth group (%d), %s", 1422 req.tag, spdk_strerror(-rc)); 1423 free_rpc_add_auth_secret(&req); 1424 return; 1425 } 1426 1427 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1428 1429 free_rpc_add_auth_secret(&req); 1430 1431 w = spdk_jsonrpc_begin_result(request); 1432 if (w == NULL) { 1433 return; 1434 } 1435 1436 spdk_json_write_bool(w, true); 1437 spdk_jsonrpc_end_result(request, w); 1438 } 1439 SPDK_RPC_REGISTER("add_secret_to_iscsi_auth_group", spdk_rpc_add_secret_to_iscsi_auth_group, 1440 SPDK_RPC_RUNTIME) 1441 1442 struct rpc_delete_auth_secret { 1443 int32_t tag; 1444 char *user; 1445 }; 1446 1447 static void 1448 free_rpc_delete_auth_secret(struct rpc_delete_auth_secret *_secret) 1449 { 1450 free(_secret->user); 1451 } 1452 1453 static const struct spdk_json_object_decoder rpc_delete_auth_secret_decoders[] = { 1454 {"tag", offsetof(struct rpc_delete_auth_secret, tag), spdk_json_decode_int32}, 1455 {"user", offsetof(struct rpc_delete_auth_secret, user), spdk_json_decode_string}, 1456 }; 1457 1458 static void 1459 spdk_rpc_delete_secret_from_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1460 const struct spdk_json_val *params) 1461 { 1462 struct rpc_delete_auth_secret req = {}; 1463 struct spdk_json_write_ctx *w; 1464 struct spdk_iscsi_auth_group *group; 1465 int rc; 1466 1467 if (spdk_json_decode_object(params, rpc_delete_auth_secret_decoders, 1468 SPDK_COUNTOF(rpc_delete_auth_secret_decoders), &req)) { 1469 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1470 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1471 "Invalid parameters"); 1472 free_rpc_delete_auth_secret(&req); 1473 return; 1474 } 1475 1476 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1477 1478 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1479 if (group == NULL) { 1480 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1481 1482 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1483 "Could not find auth group (%d)", req.tag); 1484 free_rpc_delete_auth_secret(&req); 1485 return; 1486 } 1487 1488 rc = spdk_iscsi_auth_group_delete_secret(group, req.user); 1489 if (rc != 0) { 1490 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1491 1492 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1493 "Could not delete secret from CHAP group (%d), %s", 1494 req.tag, spdk_strerror(-rc)); 1495 free_rpc_delete_auth_secret(&req); 1496 return; 1497 } 1498 1499 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1500 1501 free_rpc_delete_auth_secret(&req); 1502 1503 w = spdk_jsonrpc_begin_result(request); 1504 if (w == NULL) { 1505 return; 1506 } 1507 1508 spdk_json_write_bool(w, true); 1509 spdk_jsonrpc_end_result(request, w); 1510 } 1511 SPDK_RPC_REGISTER("delete_secret_from_iscsi_auth_group", 1512 spdk_rpc_delete_secret_from_iscsi_auth_group, SPDK_RPC_RUNTIME) 1513 1514 static void 1515 spdk_rpc_get_iscsi_auth_groups(struct spdk_jsonrpc_request *request, 1516 const struct spdk_json_val *params) 1517 { 1518 struct spdk_json_write_ctx *w; 1519 1520 if (params != NULL) { 1521 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1522 "get_iscsi_auth_groups requires no parameters"); 1523 return; 1524 } 1525 1526 w = spdk_jsonrpc_begin_result(request); 1527 if (w == NULL) { 1528 return; 1529 } 1530 1531 spdk_json_write_array_begin(w); 1532 spdk_iscsi_auth_groups_info_json(w); 1533 spdk_json_write_array_end(w); 1534 1535 spdk_jsonrpc_end_result(request, w); 1536 } 1537 SPDK_RPC_REGISTER("get_iscsi_auth_groups", spdk_rpc_get_iscsi_auth_groups, SPDK_RPC_RUNTIME) 1538