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 struct rpc_delete_target_node_ctx { 657 struct rpc_delete_target_node req; 658 struct spdk_jsonrpc_request *request; 659 }; 660 661 static void 662 rpc_delete_target_node_done(void *cb_arg, int rc) 663 { 664 struct rpc_delete_target_node_ctx *ctx = cb_arg; 665 struct spdk_json_write_ctx *w; 666 667 free_rpc_delete_target_node(&ctx->req); 668 669 w = spdk_jsonrpc_begin_result(ctx->request); 670 if (w == NULL) { 671 goto exit; 672 } 673 674 spdk_json_write_bool(w, rc == 0); 675 spdk_jsonrpc_end_result(ctx->request, w); 676 exit: 677 free(ctx); 678 } 679 680 static void 681 spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request, 682 const struct spdk_json_val *params) 683 { 684 struct rpc_delete_target_node_ctx *ctx; 685 686 ctx = calloc(1, sizeof(*ctx)); 687 if (!ctx) { 688 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 689 spdk_strerror(ENOMEM)); 690 return; 691 } 692 693 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 694 SPDK_COUNTOF(rpc_delete_target_node_decoders), 695 &ctx->req)) { 696 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 697 goto invalid; 698 } 699 700 if (ctx->req.name == NULL) { 701 SPDK_ERRLOG("missing name param\n"); 702 goto invalid; 703 } 704 705 ctx->request = request; 706 707 spdk_iscsi_shutdown_tgt_node_by_name(ctx->req.name, 708 rpc_delete_target_node_done, ctx); 709 return; 710 711 invalid: 712 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 713 free_rpc_delete_target_node(&ctx->req); 714 free(ctx); 715 } 716 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node, SPDK_RPC_RUNTIME) 717 718 static void 719 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request, 720 const struct spdk_json_val *params) 721 { 722 struct spdk_json_write_ctx *w; 723 724 if (params != NULL) { 725 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 726 "get_portal_groups requires no parameters"); 727 return; 728 } 729 730 w = spdk_jsonrpc_begin_result(request); 731 if (w == NULL) { 732 return; 733 } 734 735 spdk_json_write_array_begin(w); 736 spdk_iscsi_portal_grps_info_json(w); 737 spdk_json_write_array_end(w); 738 739 spdk_jsonrpc_end_result(request, w); 740 } 741 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups, SPDK_RPC_RUNTIME) 742 743 struct rpc_portal { 744 char *host; 745 char *port; 746 char *cpumask; 747 }; 748 749 struct rpc_portal_list { 750 size_t num_portals; 751 struct rpc_portal portals[MAX_PORTAL]; 752 }; 753 754 struct rpc_portal_group { 755 int32_t tag; 756 struct rpc_portal_list portal_list; 757 }; 758 759 static void 760 free_rpc_portal(struct rpc_portal *portal) 761 { 762 free(portal->host); 763 free(portal->port); 764 free(portal->cpumask); 765 } 766 767 static void 768 free_rpc_portal_list(struct rpc_portal_list *pl) 769 { 770 size_t i; 771 772 for (i = 0; i < pl->num_portals; i++) { 773 free_rpc_portal(&pl->portals[i]); 774 } 775 pl->num_portals = 0; 776 } 777 778 static void 779 free_rpc_portal_group(struct rpc_portal_group *pg) 780 { 781 free_rpc_portal_list(&pg->portal_list); 782 } 783 784 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 785 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 786 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 787 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 788 }; 789 790 static int 791 decode_rpc_portal(const struct spdk_json_val *val, void *out) 792 { 793 struct rpc_portal *portal = out; 794 795 return spdk_json_decode_object(val, rpc_portal_decoders, 796 SPDK_COUNTOF(rpc_portal_decoders), 797 portal); 798 } 799 800 static int 801 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 802 { 803 struct rpc_portal_list *list = out; 804 805 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 806 sizeof(struct rpc_portal)); 807 } 808 809 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 810 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 811 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 812 }; 813 814 static void 815 spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request, 816 const struct spdk_json_val *params) 817 { 818 struct rpc_portal_group req = {}; 819 struct spdk_iscsi_portal_grp *pg = NULL; 820 struct spdk_iscsi_portal *portal; 821 struct spdk_json_write_ctx *w; 822 size_t i = 0; 823 int rc = -1; 824 825 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 826 SPDK_COUNTOF(rpc_portal_group_decoders), 827 &req)) { 828 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 829 goto out; 830 } 831 832 pg = spdk_iscsi_portal_grp_create(req.tag); 833 if (pg == NULL) { 834 SPDK_ERRLOG("portal_grp_create failed\n"); 835 goto out; 836 } 837 for (i = 0; i < req.portal_list.num_portals; i++) { 838 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 839 req.portal_list.portals[i].port, 840 req.portal_list.portals[i].cpumask); 841 if (portal == NULL) { 842 SPDK_ERRLOG("portal_create failed\n"); 843 goto out; 844 } 845 spdk_iscsi_portal_grp_add_portal(pg, portal); 846 } 847 848 rc = spdk_iscsi_portal_grp_open(pg); 849 if (rc != 0) { 850 SPDK_ERRLOG("portal_grp_open failed\n"); 851 goto out; 852 } 853 854 rc = spdk_iscsi_portal_grp_register(pg); 855 if (rc != 0) { 856 SPDK_ERRLOG("portal_grp_register failed\n"); 857 } 858 859 out: 860 if (rc == 0) { 861 w = spdk_jsonrpc_begin_result(request); 862 if (w != NULL) { 863 spdk_json_write_bool(w, true); 864 spdk_jsonrpc_end_result(request, w); 865 } 866 } else { 867 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 868 869 if (pg != NULL) { 870 spdk_iscsi_portal_grp_release(pg); 871 } 872 } 873 free_rpc_portal_group(&req); 874 } 875 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group, SPDK_RPC_RUNTIME) 876 877 struct rpc_delete_portal_group { 878 int32_t tag; 879 }; 880 881 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 882 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 883 }; 884 885 static void 886 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request, 887 const struct spdk_json_val *params) 888 { 889 struct rpc_delete_portal_group req = {}; 890 struct spdk_json_write_ctx *w; 891 struct spdk_iscsi_portal_grp *pg; 892 893 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 894 SPDK_COUNTOF(rpc_delete_portal_group_decoders), 895 &req)) { 896 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 897 goto invalid; 898 } 899 900 pg = spdk_iscsi_portal_grp_unregister(req.tag); 901 if (!pg) { 902 goto invalid; 903 } 904 905 spdk_iscsi_tgt_node_delete_map(pg, NULL); 906 spdk_iscsi_portal_grp_release(pg); 907 908 w = spdk_jsonrpc_begin_result(request); 909 if (w == NULL) { 910 return; 911 } 912 913 spdk_json_write_bool(w, true); 914 spdk_jsonrpc_end_result(request, w); 915 return; 916 917 invalid: 918 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 919 } 920 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group, SPDK_RPC_RUNTIME) 921 922 static void 923 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request, 924 const struct spdk_json_val *params) 925 { 926 struct spdk_json_write_ctx *w; 927 struct spdk_iscsi_conn *conns = g_conns_array; 928 int i; 929 uint16_t tsih; 930 931 if (params != NULL) { 932 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 933 "get_iscsi_connections requires no parameters"); 934 return; 935 } 936 937 w = spdk_jsonrpc_begin_result(request); 938 if (w == NULL) { 939 return; 940 } 941 942 spdk_json_write_array_begin(w); 943 944 for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) { 945 struct spdk_iscsi_conn *c = &conns[i]; 946 947 if (!c->is_valid) { 948 continue; 949 } 950 951 spdk_json_write_object_begin(w); 952 953 spdk_json_write_named_int32(w, "id", c->id); 954 955 spdk_json_write_named_int32(w, "cid", c->cid); 956 957 /* 958 * If we try to return data for a connection that has not 959 * logged in yet, the session will not be set. So in this 960 * case, return -1 for the tsih rather than segfaulting 961 * on the null c->sess. 962 */ 963 if (c->sess == NULL) { 964 tsih = -1; 965 } else { 966 tsih = c->sess->tsih; 967 } 968 spdk_json_write_named_int32(w, "tsih", tsih); 969 970 spdk_json_write_named_int32(w, "lcore_id", c->lcore); 971 972 spdk_json_write_named_string(w, "initiator_addr", c->initiator_addr); 973 974 spdk_json_write_named_string(w, "target_addr", c->target_addr); 975 976 spdk_json_write_named_string(w, "target_node_name", c->target_short_name); 977 978 spdk_json_write_object_end(w); 979 } 980 spdk_json_write_array_end(w); 981 982 spdk_jsonrpc_end_result(request, w); 983 } 984 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections, SPDK_RPC_RUNTIME) 985 986 struct rpc_target_lun { 987 char *name; 988 char *bdev_name; 989 int32_t lun_id; 990 }; 991 992 static void 993 free_rpc_target_lun(struct rpc_target_lun *req) 994 { 995 free(req->name); 996 free(req->bdev_name); 997 } 998 999 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1000 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1001 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1002 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1003 }; 1004 1005 static void 1006 spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request, 1007 const struct spdk_json_val *params) 1008 { 1009 struct rpc_target_lun req = {}; 1010 struct spdk_json_write_ctx *w; 1011 struct spdk_iscsi_tgt_node *target; 1012 int rc; 1013 1014 req.lun_id = -1; 1015 1016 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1017 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1018 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1019 goto invalid; 1020 } 1021 1022 target = spdk_iscsi_find_tgt_node(req.name); 1023 if (target == NULL) { 1024 SPDK_ERRLOG("target is not found\n"); 1025 goto invalid; 1026 } 1027 1028 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1029 if (rc < 0) { 1030 SPDK_ERRLOG("add lun failed\n"); 1031 goto invalid; 1032 } 1033 1034 free_rpc_target_lun(&req); 1035 1036 w = spdk_jsonrpc_begin_result(request); 1037 if (w == NULL) { 1038 return; 1039 } 1040 1041 spdk_json_write_bool(w, true); 1042 spdk_jsonrpc_end_result(request, w); 1043 return; 1044 1045 invalid: 1046 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1047 "Invalid parameters"); 1048 free_rpc_target_lun(&req); 1049 } 1050 SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME) 1051 1052 struct rpc_target_auth { 1053 char *name; 1054 bool disable_chap; 1055 bool require_chap; 1056 bool mutual_chap; 1057 int32_t chap_group; 1058 }; 1059 1060 static void 1061 free_rpc_target_auth(struct rpc_target_auth *req) 1062 { 1063 free(req->name); 1064 } 1065 1066 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1067 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1068 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1069 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1070 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1071 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1072 }; 1073 1074 static void 1075 spdk_rpc_set_iscsi_target_node_auth(struct spdk_jsonrpc_request *request, 1076 const struct spdk_json_val *params) 1077 { 1078 struct rpc_target_auth req = {}; 1079 struct spdk_json_write_ctx *w; 1080 struct spdk_iscsi_tgt_node *target; 1081 int rc; 1082 1083 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1084 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1085 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1086 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1087 "Invalid parameters"); 1088 goto exit; 1089 } 1090 1091 target = spdk_iscsi_find_tgt_node(req.name); 1092 if (target == NULL) { 1093 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1094 "Could not find target %s", req.name); 1095 goto exit; 1096 } 1097 1098 rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1099 req.mutual_chap, req.chap_group); 1100 if (rc < 0) { 1101 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1102 "Invalid combination of auth params"); 1103 goto exit; 1104 } 1105 1106 free_rpc_target_auth(&req); 1107 1108 w = spdk_jsonrpc_begin_result(request); 1109 if (w == NULL) { 1110 return; 1111 } 1112 1113 spdk_json_write_bool(w, true); 1114 spdk_jsonrpc_end_result(request, w); 1115 return; 1116 1117 exit: 1118 free_rpc_target_auth(&req); 1119 } 1120 SPDK_RPC_REGISTER("set_iscsi_target_node_auth", spdk_rpc_set_iscsi_target_node_auth, 1121 SPDK_RPC_RUNTIME) 1122 1123 static void 1124 spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request, 1125 const struct spdk_json_val *params) 1126 { 1127 struct spdk_json_write_ctx *w; 1128 1129 if (params != NULL) { 1130 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1131 "get_iscsi_global_params requires no parameters"); 1132 return; 1133 } 1134 1135 w = spdk_jsonrpc_begin_result(request); 1136 if (w == NULL) { 1137 return; 1138 } 1139 1140 spdk_iscsi_opts_info_json(w); 1141 1142 spdk_jsonrpc_end_result(request, w); 1143 } 1144 SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME) 1145 1146 struct rpc_discovery_auth { 1147 bool disable_chap; 1148 bool require_chap; 1149 bool mutual_chap; 1150 int32_t chap_group; 1151 }; 1152 1153 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1154 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1155 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1156 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1157 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1158 }; 1159 1160 static void 1161 spdk_rpc_set_iscsi_discovery_auth(struct spdk_jsonrpc_request *request, 1162 const struct spdk_json_val *params) 1163 { 1164 struct rpc_discovery_auth req = {}; 1165 struct spdk_json_write_ctx *w; 1166 int rc; 1167 1168 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1169 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1170 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1171 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1172 "Invalid parameters"); 1173 return; 1174 } 1175 1176 rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1177 req.mutual_chap, req.chap_group); 1178 if (rc < 0) { 1179 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1180 "Invalid combination of CHAP params"); 1181 return; 1182 } 1183 1184 w = spdk_jsonrpc_begin_result(request); 1185 if (w == NULL) { 1186 return; 1187 } 1188 1189 spdk_json_write_bool(w, true); 1190 spdk_jsonrpc_end_result(request, w); 1191 } 1192 SPDK_RPC_REGISTER("set_iscsi_discovery_auth", spdk_rpc_set_iscsi_discovery_auth, SPDK_RPC_RUNTIME) 1193 1194 1195 #define MAX_AUTH_SECRETS 64 1196 1197 struct rpc_auth_secret { 1198 char *user; 1199 char *secret; 1200 char *muser; 1201 char *msecret; 1202 }; 1203 1204 static void 1205 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1206 { 1207 free(_secret->user); 1208 free(_secret->secret); 1209 free(_secret->muser); 1210 free(_secret->msecret); 1211 } 1212 1213 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1214 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1215 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1216 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1217 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1218 }; 1219 1220 static int 1221 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1222 { 1223 struct rpc_auth_secret *_secret = out; 1224 1225 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1226 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1227 } 1228 1229 struct rpc_auth_secrets { 1230 size_t num_secret; 1231 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1232 }; 1233 1234 static void 1235 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1236 { 1237 size_t i; 1238 1239 for (i = 0; i < secrets->num_secret; i++) { 1240 free_rpc_auth_secret(&secrets->secrets[i]); 1241 } 1242 } 1243 1244 static int 1245 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1246 { 1247 struct rpc_auth_secrets *secrets = out; 1248 1249 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1250 MAX_AUTH_SECRETS, &secrets->num_secret, 1251 sizeof(struct rpc_auth_secret)); 1252 } 1253 1254 struct rpc_auth_group { 1255 int32_t tag; 1256 struct rpc_auth_secrets secrets; 1257 }; 1258 1259 static void 1260 free_rpc_auth_group(struct rpc_auth_group *group) 1261 { 1262 free_rpc_auth_secrets(&group->secrets); 1263 } 1264 1265 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1266 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1267 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1268 }; 1269 1270 static void 1271 spdk_rpc_add_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1272 const struct spdk_json_val *params) 1273 { 1274 struct rpc_auth_group req = {}; 1275 struct rpc_auth_secret *_secret; 1276 struct spdk_json_write_ctx *w; 1277 struct spdk_iscsi_auth_group *group = NULL; 1278 int rc; 1279 size_t i; 1280 1281 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1282 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1283 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1284 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1285 "Invalid parameters"); 1286 free_rpc_auth_group(&req); 1287 return; 1288 } 1289 1290 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1291 1292 rc = spdk_iscsi_add_auth_group(req.tag, &group); 1293 if (rc != 0) { 1294 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1295 1296 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1297 "Could not add auth group (%d), %s", 1298 req.tag, spdk_strerror(-rc)); 1299 free_rpc_auth_group(&req); 1300 return; 1301 } 1302 1303 for (i = 0; i < req.secrets.num_secret; i++) { 1304 _secret = &req.secrets.secrets[i]; 1305 rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1306 _secret->muser, _secret->msecret); 1307 if (rc != 0) { 1308 spdk_iscsi_delete_auth_group(group); 1309 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1310 1311 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1312 "Could not add secret to auth group (%d), %s", 1313 req.tag, spdk_strerror(-rc)); 1314 free_rpc_auth_group(&req); 1315 return; 1316 } 1317 } 1318 1319 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1320 1321 free_rpc_auth_group(&req); 1322 1323 w = spdk_jsonrpc_begin_result(request); 1324 if (w == NULL) { 1325 return; 1326 } 1327 1328 spdk_json_write_bool(w, true); 1329 spdk_jsonrpc_end_result(request, w); 1330 } 1331 SPDK_RPC_REGISTER("add_iscsi_auth_group", spdk_rpc_add_iscsi_auth_group, SPDK_RPC_RUNTIME) 1332 1333 struct rpc_delete_auth_group { 1334 int32_t tag; 1335 }; 1336 1337 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1338 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1339 }; 1340 1341 static void 1342 spdk_rpc_delete_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1343 const struct spdk_json_val *params) 1344 { 1345 struct rpc_delete_auth_group req = {}; 1346 struct spdk_json_write_ctx *w; 1347 struct spdk_iscsi_auth_group *group; 1348 1349 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1350 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1351 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1352 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1353 "Invalid parameters"); 1354 return; 1355 } 1356 1357 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1358 1359 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1360 if (group == NULL) { 1361 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1362 1363 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1364 "Could not find auth group (%d)", req.tag); 1365 return; 1366 } 1367 1368 spdk_iscsi_delete_auth_group(group); 1369 1370 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1371 1372 w = spdk_jsonrpc_begin_result(request); 1373 if (w == NULL) { 1374 return; 1375 } 1376 1377 spdk_json_write_bool(w, true); 1378 spdk_jsonrpc_end_result(request, w); 1379 } 1380 SPDK_RPC_REGISTER("delete_iscsi_auth_group", spdk_rpc_delete_iscsi_auth_group, SPDK_RPC_RUNTIME) 1381 1382 struct rpc_add_auth_secret { 1383 int32_t tag; 1384 char *user; 1385 char *secret; 1386 char *muser; 1387 char *msecret; 1388 }; 1389 1390 static void 1391 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1392 { 1393 free(_secret->user); 1394 free(_secret->secret); 1395 free(_secret->muser); 1396 free(_secret->msecret); 1397 } 1398 1399 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1400 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1401 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1402 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1403 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1404 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1405 }; 1406 1407 static void 1408 spdk_rpc_add_secret_to_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1409 const struct spdk_json_val *params) 1410 { 1411 struct rpc_add_auth_secret req = {}; 1412 struct spdk_json_write_ctx *w; 1413 struct spdk_iscsi_auth_group *group; 1414 int rc; 1415 1416 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1417 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1418 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1419 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1420 "Invalid parameters"); 1421 free_rpc_add_auth_secret(&req); 1422 return; 1423 } 1424 1425 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1426 1427 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1428 if (group == NULL) { 1429 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1430 1431 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1432 "Could not find auth group (%d)", req.tag); 1433 free_rpc_add_auth_secret(&req); 1434 return; 1435 } 1436 1437 rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1438 if (rc != 0) { 1439 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1440 1441 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1442 "Could not add secret to auth group (%d), %s", 1443 req.tag, spdk_strerror(-rc)); 1444 free_rpc_add_auth_secret(&req); 1445 return; 1446 } 1447 1448 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1449 1450 free_rpc_add_auth_secret(&req); 1451 1452 w = spdk_jsonrpc_begin_result(request); 1453 if (w == NULL) { 1454 return; 1455 } 1456 1457 spdk_json_write_bool(w, true); 1458 spdk_jsonrpc_end_result(request, w); 1459 } 1460 SPDK_RPC_REGISTER("add_secret_to_iscsi_auth_group", spdk_rpc_add_secret_to_iscsi_auth_group, 1461 SPDK_RPC_RUNTIME) 1462 1463 struct rpc_delete_auth_secret { 1464 int32_t tag; 1465 char *user; 1466 }; 1467 1468 static void 1469 free_rpc_delete_auth_secret(struct rpc_delete_auth_secret *_secret) 1470 { 1471 free(_secret->user); 1472 } 1473 1474 static const struct spdk_json_object_decoder rpc_delete_auth_secret_decoders[] = { 1475 {"tag", offsetof(struct rpc_delete_auth_secret, tag), spdk_json_decode_int32}, 1476 {"user", offsetof(struct rpc_delete_auth_secret, user), spdk_json_decode_string}, 1477 }; 1478 1479 static void 1480 spdk_rpc_delete_secret_from_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1481 const struct spdk_json_val *params) 1482 { 1483 struct rpc_delete_auth_secret req = {}; 1484 struct spdk_json_write_ctx *w; 1485 struct spdk_iscsi_auth_group *group; 1486 int rc; 1487 1488 if (spdk_json_decode_object(params, rpc_delete_auth_secret_decoders, 1489 SPDK_COUNTOF(rpc_delete_auth_secret_decoders), &req)) { 1490 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1491 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1492 "Invalid parameters"); 1493 free_rpc_delete_auth_secret(&req); 1494 return; 1495 } 1496 1497 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1498 1499 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1500 if (group == NULL) { 1501 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1502 1503 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1504 "Could not find auth group (%d)", req.tag); 1505 free_rpc_delete_auth_secret(&req); 1506 return; 1507 } 1508 1509 rc = spdk_iscsi_auth_group_delete_secret(group, req.user); 1510 if (rc != 0) { 1511 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1512 1513 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1514 "Could not delete secret from CHAP group (%d), %s", 1515 req.tag, spdk_strerror(-rc)); 1516 free_rpc_delete_auth_secret(&req); 1517 return; 1518 } 1519 1520 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1521 1522 free_rpc_delete_auth_secret(&req); 1523 1524 w = spdk_jsonrpc_begin_result(request); 1525 if (w == NULL) { 1526 return; 1527 } 1528 1529 spdk_json_write_bool(w, true); 1530 spdk_jsonrpc_end_result(request, w); 1531 } 1532 SPDK_RPC_REGISTER("delete_secret_from_iscsi_auth_group", 1533 spdk_rpc_delete_secret_from_iscsi_auth_group, SPDK_RPC_RUNTIME) 1534 1535 static void 1536 spdk_rpc_get_iscsi_auth_groups(struct spdk_jsonrpc_request *request, 1537 const struct spdk_json_val *params) 1538 { 1539 struct spdk_json_write_ctx *w; 1540 1541 if (params != NULL) { 1542 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1543 "get_iscsi_auth_groups requires no parameters"); 1544 return; 1545 } 1546 1547 w = spdk_jsonrpc_begin_result(request); 1548 if (w == NULL) { 1549 return; 1550 } 1551 1552 spdk_json_write_array_begin(w); 1553 spdk_iscsi_auth_groups_info_json(w); 1554 spdk_json_write_array_end(w); 1555 1556 spdk_jsonrpc_end_result(request, w); 1557 } 1558 SPDK_RPC_REGISTER("get_iscsi_auth_groups", spdk_rpc_get_iscsi_auth_groups, SPDK_RPC_RUNTIME) 1559