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/string.h" 44 #include "spdk/log.h" 45 46 static void 47 rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request, 48 const struct spdk_json_val *params) 49 { 50 struct spdk_json_write_ctx *w; 51 52 if (params != NULL) { 53 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 54 "iscsi_get_initiator_groups requires no parameters"); 55 return; 56 } 57 58 w = spdk_jsonrpc_begin_result(request); 59 spdk_json_write_array_begin(w); 60 iscsi_init_grps_info_json(w); 61 spdk_json_write_array_end(w); 62 63 spdk_jsonrpc_end_result(request, w); 64 } 65 SPDK_RPC_REGISTER("iscsi_get_initiator_groups", rpc_iscsi_get_initiator_groups, 66 SPDK_RPC_RUNTIME) 67 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_initiator_groups, get_initiator_groups) 68 69 struct rpc_initiator_list { 70 size_t num_initiators; 71 char *initiators[MAX_INITIATOR]; 72 }; 73 74 static int 75 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 76 { 77 struct rpc_initiator_list *list = out; 78 79 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 80 &list->num_initiators, sizeof(char *)); 81 } 82 83 static void 84 free_rpc_initiator_list(struct rpc_initiator_list *list) 85 { 86 size_t i; 87 88 for (i = 0; i < list->num_initiators; i++) { 89 free(list->initiators[i]); 90 } 91 } 92 93 struct rpc_netmask_list { 94 size_t num_netmasks; 95 char *netmasks[MAX_NETMASK]; 96 }; 97 98 static int 99 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 100 { 101 struct rpc_netmask_list *list = out; 102 103 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 104 &list->num_netmasks, sizeof(char *)); 105 } 106 107 static void 108 free_rpc_netmask_list(struct rpc_netmask_list *list) 109 { 110 size_t i; 111 112 for (i = 0; i < list->num_netmasks; i++) { 113 free(list->netmasks[i]); 114 } 115 } 116 117 struct rpc_initiator_group { 118 int32_t tag; 119 struct rpc_initiator_list initiator_list; 120 struct rpc_netmask_list netmask_list; 121 }; 122 123 static void 124 free_rpc_initiator_group(struct rpc_initiator_group *ig) 125 { 126 free_rpc_initiator_list(&ig->initiator_list); 127 free_rpc_netmask_list(&ig->netmask_list); 128 } 129 130 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 131 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 132 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 133 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 134 }; 135 136 static void 137 rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request, 138 const struct spdk_json_val *params) 139 { 140 struct rpc_initiator_group req = {}; 141 142 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 143 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 144 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 145 goto invalid; 146 } 147 148 if (req.initiator_list.num_initiators == 0 || 149 req.netmask_list.num_netmasks == 0) { 150 goto invalid; 151 } 152 153 if (iscsi_init_grp_create_from_initiator_list(req.tag, 154 req.initiator_list.num_initiators, 155 req.initiator_list.initiators, 156 req.netmask_list.num_netmasks, 157 req.netmask_list.netmasks)) { 158 SPDK_ERRLOG("create_from_initiator_list failed\n"); 159 goto invalid; 160 } 161 162 free_rpc_initiator_group(&req); 163 164 spdk_jsonrpc_send_bool_response(request, true); 165 return; 166 167 invalid: 168 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 169 free_rpc_initiator_group(&req); 170 } 171 SPDK_RPC_REGISTER("iscsi_create_initiator_group", rpc_iscsi_create_initiator_group, 172 SPDK_RPC_RUNTIME) 173 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_initiator_group, add_initiator_group) 174 175 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 176 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 177 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 178 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 179 }; 180 181 static void 182 rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request, 183 const struct spdk_json_val *params) 184 { 185 struct rpc_initiator_group req = {}; 186 187 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 188 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 189 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 190 goto invalid; 191 } 192 193 if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 194 req.initiator_list.num_initiators, 195 req.initiator_list.initiators, 196 req.netmask_list.num_netmasks, 197 req.netmask_list.netmasks)) { 198 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 199 goto invalid; 200 } 201 202 free_rpc_initiator_group(&req); 203 204 spdk_jsonrpc_send_bool_response(request, true); 205 return; 206 207 invalid: 208 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 209 free_rpc_initiator_group(&req); 210 } 211 SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators", 212 rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME) 213 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_initiator_group_add_initiators, 214 add_initiators_to_initiator_group) 215 216 static void 217 rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request, 218 const struct spdk_json_val *params) 219 { 220 struct rpc_initiator_group req = {}; 221 222 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 223 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 224 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 225 goto invalid; 226 } 227 228 if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 229 req.initiator_list.num_initiators, 230 req.initiator_list.initiators, 231 req.netmask_list.num_netmasks, 232 req.netmask_list.netmasks)) { 233 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 234 goto invalid; 235 } 236 237 free_rpc_initiator_group(&req); 238 239 spdk_jsonrpc_send_bool_response(request, true); 240 return; 241 242 invalid: 243 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 244 free_rpc_initiator_group(&req); 245 } 246 SPDK_RPC_REGISTER("iscsi_initiator_group_remove_initiators", 247 rpc_iscsi_initiator_group_remove_initiators, SPDK_RPC_RUNTIME) 248 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_initiator_group_remove_initiators, 249 delete_initiators_from_initiator_group) 250 251 struct rpc_iscsi_delete_initiator_group { 252 int32_t tag; 253 }; 254 255 static const struct spdk_json_object_decoder rpc_iscsi_delete_initiator_group_decoders[] = { 256 {"tag", offsetof(struct rpc_iscsi_delete_initiator_group, tag), spdk_json_decode_int32}, 257 }; 258 259 static void 260 rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request, 261 const struct spdk_json_val *params) 262 { 263 struct rpc_iscsi_delete_initiator_group req = {}; 264 struct spdk_iscsi_init_grp *ig; 265 266 if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders, 267 SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders), 268 &req)) { 269 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 270 goto invalid; 271 } 272 273 ig = iscsi_init_grp_unregister(req.tag); 274 if (!ig) { 275 goto invalid; 276 } 277 iscsi_tgt_node_delete_map(NULL, ig); 278 iscsi_init_grp_destroy(ig); 279 280 spdk_jsonrpc_send_bool_response(request, true); 281 return; 282 283 invalid: 284 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 285 } 286 SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group, 287 SPDK_RPC_RUNTIME) 288 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_initiator_group, delete_initiator_group) 289 290 static void 291 rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request *request, 292 const struct spdk_json_val *params) 293 { 294 struct spdk_json_write_ctx *w; 295 296 if (params != NULL) { 297 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 298 "iscsi_get_target_nodes requires no parameters"); 299 return; 300 } 301 302 w = spdk_jsonrpc_begin_result(request); 303 spdk_json_write_array_begin(w); 304 iscsi_tgt_nodes_info_json(w); 305 spdk_json_write_array_end(w); 306 307 spdk_jsonrpc_end_result(request, w); 308 } 309 SPDK_RPC_REGISTER("iscsi_get_target_nodes", rpc_iscsi_get_target_nodes, SPDK_RPC_RUNTIME) 310 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_target_nodes, get_target_nodes) 311 312 struct rpc_pg_ig_map { 313 int32_t pg_tag; 314 int32_t ig_tag; 315 }; 316 317 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 318 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 319 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 320 }; 321 322 static int 323 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 324 { 325 struct rpc_pg_ig_map *pg_ig_map = out; 326 327 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 328 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 329 pg_ig_map); 330 } 331 332 struct rpc_pg_ig_maps { 333 size_t num_maps; 334 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 335 }; 336 337 static int 338 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 339 { 340 struct rpc_pg_ig_maps *pg_ig_maps = out; 341 342 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 343 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 344 sizeof(struct rpc_pg_ig_map)); 345 } 346 347 #define RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN 64 348 349 struct rpc_lun { 350 char *bdev_name; 351 int32_t lun_id; 352 }; 353 354 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 355 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 356 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 357 }; 358 359 static int 360 decode_rpc_lun(const struct spdk_json_val *val, void *out) 361 { 362 struct rpc_lun *lun = out; 363 364 return spdk_json_decode_object(val, rpc_lun_decoders, 365 SPDK_COUNTOF(rpc_lun_decoders), lun); 366 } 367 368 struct rpc_luns { 369 size_t num_luns; 370 struct rpc_lun luns[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN]; 371 }; 372 373 static int 374 decode_rpc_luns(const struct spdk_json_val *val, void *out) 375 { 376 struct rpc_luns *luns = out; 377 378 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 379 RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN, 380 &luns->num_luns, sizeof(struct rpc_lun)); 381 } 382 383 static void 384 free_rpc_luns(struct rpc_luns *p) 385 { 386 size_t i; 387 388 for (i = 0; i < p->num_luns; i++) { 389 free(p->luns[i].bdev_name); 390 } 391 } 392 393 struct rpc_target_node { 394 char *name; 395 char *alias_name; 396 397 struct rpc_pg_ig_maps pg_ig_maps; 398 struct rpc_luns luns; 399 400 int32_t queue_depth; 401 bool disable_chap; 402 bool require_chap; 403 bool mutual_chap; 404 int32_t chap_group; 405 406 bool header_digest; 407 bool data_digest; 408 }; 409 410 static void 411 free_rpc_target_node(struct rpc_target_node *req) 412 { 413 free(req->name); 414 free(req->alias_name); 415 free_rpc_luns(&req->luns); 416 } 417 418 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 419 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 420 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 421 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 422 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 423 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 424 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 425 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 426 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 427 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 428 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 429 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 430 }; 431 432 static void 433 rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request, 434 const struct spdk_json_val *params) 435 { 436 struct rpc_target_node req = {}; 437 struct spdk_iscsi_tgt_node *target; 438 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 439 char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 440 int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 441 size_t i; 442 443 if (spdk_json_decode_object(params, rpc_target_node_decoders, 444 SPDK_COUNTOF(rpc_target_node_decoders), 445 &req)) { 446 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 447 goto invalid; 448 } 449 450 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 451 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 452 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 453 } 454 455 for (i = 0; i < req.luns.num_luns; i++) { 456 bdev_names[i] = req.luns.luns[i].bdev_name; 457 lun_ids[i] = req.luns.luns[i].lun_id; 458 } 459 460 /* 461 * Use default parameters in a few places: 462 * index = -1 : automatically pick an index for the new target node 463 * alias = NULL 464 */ 465 target = iscsi_tgt_node_construct(-1, req.name, req.alias_name, 466 pg_tags, 467 ig_tags, 468 req.pg_ig_maps.num_maps, 469 (const char **)bdev_names, 470 lun_ids, 471 req.luns.num_luns, 472 req.queue_depth, 473 req.disable_chap, 474 req.require_chap, 475 req.mutual_chap, 476 req.chap_group, 477 req.header_digest, 478 req.data_digest); 479 480 if (target == NULL) { 481 goto invalid; 482 } 483 484 free_rpc_target_node(&req); 485 486 spdk_jsonrpc_send_bool_response(request, true); 487 return; 488 489 invalid: 490 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 491 free_rpc_target_node(&req); 492 } 493 SPDK_RPC_REGISTER("iscsi_create_target_node", rpc_iscsi_create_target_node, SPDK_RPC_RUNTIME) 494 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_target_node, construct_target_node) 495 496 struct rpc_tgt_node_pg_ig_maps { 497 char *name; 498 struct rpc_pg_ig_maps pg_ig_maps; 499 }; 500 501 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 502 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 503 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 504 }; 505 506 static void 507 rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 508 const struct spdk_json_val *params) 509 { 510 struct rpc_tgt_node_pg_ig_maps req = {}; 511 struct spdk_iscsi_tgt_node *target; 512 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 513 size_t i; 514 int rc; 515 516 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 517 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 518 &req)) { 519 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 520 goto invalid; 521 } 522 523 target = iscsi_find_tgt_node(req.name); 524 if (target == NULL) { 525 SPDK_ERRLOG("target is not found\n"); 526 goto invalid; 527 } 528 529 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 530 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 531 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 532 } 533 534 rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags, 535 req.pg_ig_maps.num_maps); 536 if (rc < 0) { 537 SPDK_ERRLOG("add pg-ig maps failed\n"); 538 goto invalid; 539 } 540 541 free(req.name); 542 543 spdk_jsonrpc_send_bool_response(request, true); 544 return; 545 546 invalid: 547 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 548 "Invalid parameters"); 549 free(req.name); 550 } 551 SPDK_RPC_REGISTER("iscsi_target_node_add_pg_ig_maps", 552 rpc_iscsi_target_node_add_pg_ig_maps, SPDK_RPC_RUNTIME) 553 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_pg_ig_maps, add_pg_ig_maps) 554 555 static void 556 rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request, 557 const struct spdk_json_val *params) 558 { 559 struct rpc_tgt_node_pg_ig_maps req = {}; 560 struct spdk_iscsi_tgt_node *target; 561 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 562 size_t i; 563 int rc; 564 565 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 566 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 567 &req)) { 568 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 569 goto invalid; 570 } 571 572 target = iscsi_find_tgt_node(req.name); 573 if (target == NULL) { 574 SPDK_ERRLOG("target is not found\n"); 575 goto invalid; 576 } 577 578 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 579 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 580 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 581 } 582 583 rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags, 584 req.pg_ig_maps.num_maps); 585 if (rc < 0) { 586 SPDK_ERRLOG("remove pg-ig maps failed\n"); 587 goto invalid; 588 } 589 590 free(req.name); 591 592 spdk_jsonrpc_send_bool_response(request, true); 593 return; 594 595 invalid: 596 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 597 "Invalid parameters"); 598 free(req.name); 599 } 600 SPDK_RPC_REGISTER("iscsi_target_node_remove_pg_ig_maps", 601 rpc_iscsi_target_node_remove_pg_ig_maps, SPDK_RPC_RUNTIME) 602 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_remove_pg_ig_maps, 603 delete_pg_ig_maps) 604 605 struct rpc_iscsi_delete_target_node { 606 char *name; 607 }; 608 609 static void 610 free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r) 611 { 612 free(r->name); 613 } 614 615 static const struct spdk_json_object_decoder rpc_iscsi_delete_target_node_decoders[] = { 616 {"name", offsetof(struct rpc_iscsi_delete_target_node, name), spdk_json_decode_string}, 617 }; 618 619 struct rpc_iscsi_delete_target_node_ctx { 620 struct rpc_iscsi_delete_target_node req; 621 struct spdk_jsonrpc_request *request; 622 }; 623 624 static void 625 rpc_iscsi_delete_target_node_done(void *cb_arg, int rc) 626 { 627 struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg; 628 629 free_rpc_iscsi_delete_target_node(&ctx->req); 630 spdk_jsonrpc_send_bool_response(ctx->request, rc == 0); 631 free(ctx); 632 } 633 634 static void 635 rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request, 636 const struct spdk_json_val *params) 637 { 638 struct rpc_iscsi_delete_target_node_ctx *ctx; 639 640 ctx = calloc(1, sizeof(*ctx)); 641 if (!ctx) { 642 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 643 spdk_strerror(ENOMEM)); 644 return; 645 } 646 647 if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders, 648 SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders), 649 &ctx->req)) { 650 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 651 goto invalid; 652 } 653 654 if (ctx->req.name == NULL) { 655 SPDK_ERRLOG("missing name param\n"); 656 goto invalid; 657 } 658 659 ctx->request = request; 660 661 iscsi_shutdown_tgt_node_by_name(ctx->req.name, 662 rpc_iscsi_delete_target_node_done, ctx); 663 return; 664 665 invalid: 666 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 667 free_rpc_iscsi_delete_target_node(&ctx->req); 668 free(ctx); 669 } 670 SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME) 671 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_target_node, delete_target_node) 672 673 static void 674 rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request, 675 const struct spdk_json_val *params) 676 { 677 struct spdk_json_write_ctx *w; 678 679 if (params != NULL) { 680 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 681 "iscsi_get_portal_groups requires no parameters"); 682 return; 683 } 684 685 w = spdk_jsonrpc_begin_result(request); 686 spdk_json_write_array_begin(w); 687 iscsi_portal_grps_info_json(w); 688 spdk_json_write_array_end(w); 689 690 spdk_jsonrpc_end_result(request, w); 691 } 692 SPDK_RPC_REGISTER("iscsi_get_portal_groups", rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME) 693 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_portal_groups, get_portal_groups) 694 695 struct rpc_portal { 696 char *host; 697 char *port; 698 }; 699 700 struct rpc_portal_list { 701 size_t num_portals; 702 struct rpc_portal portals[MAX_PORTAL]; 703 }; 704 705 struct rpc_portal_group { 706 int32_t tag; 707 struct rpc_portal_list portal_list; 708 bool is_private; 709 }; 710 711 static void 712 free_rpc_portal(struct rpc_portal *portal) 713 { 714 free(portal->host); 715 free(portal->port); 716 } 717 718 static void 719 free_rpc_portal_list(struct rpc_portal_list *pl) 720 { 721 size_t i; 722 723 for (i = 0; i < pl->num_portals; i++) { 724 free_rpc_portal(&pl->portals[i]); 725 } 726 pl->num_portals = 0; 727 } 728 729 static void 730 free_rpc_portal_group(struct rpc_portal_group *pg) 731 { 732 free_rpc_portal_list(&pg->portal_list); 733 } 734 735 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 736 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 737 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 738 }; 739 740 static int 741 decode_rpc_portal(const struct spdk_json_val *val, void *out) 742 { 743 struct rpc_portal *portal = out; 744 745 return spdk_json_decode_object(val, rpc_portal_decoders, 746 SPDK_COUNTOF(rpc_portal_decoders), 747 portal); 748 } 749 750 static int 751 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 752 { 753 struct rpc_portal_list *list = out; 754 755 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 756 sizeof(struct rpc_portal)); 757 } 758 759 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 760 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 761 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 762 {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true}, 763 }; 764 765 static void 766 rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 767 const struct spdk_json_val *params) 768 { 769 struct rpc_portal_group req = {}; 770 struct spdk_iscsi_portal_grp *pg = NULL; 771 struct spdk_iscsi_portal *portal; 772 size_t i = 0; 773 int rc = -1; 774 775 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 776 SPDK_COUNTOF(rpc_portal_group_decoders), 777 &req)) { 778 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 779 goto out; 780 } 781 782 pg = iscsi_portal_grp_create(req.tag, req.is_private); 783 if (pg == NULL) { 784 SPDK_ERRLOG("portal_grp_create failed\n"); 785 goto out; 786 } 787 for (i = 0; i < req.portal_list.num_portals; i++) { 788 portal = iscsi_portal_create(req.portal_list.portals[i].host, 789 req.portal_list.portals[i].port); 790 if (portal == NULL) { 791 SPDK_ERRLOG("portal_create failed\n"); 792 goto out; 793 } 794 iscsi_portal_grp_add_portal(pg, portal); 795 } 796 797 rc = iscsi_portal_grp_open(pg); 798 if (rc != 0) { 799 SPDK_ERRLOG("portal_grp_open failed\n"); 800 goto out; 801 } 802 803 rc = iscsi_portal_grp_register(pg); 804 if (rc != 0) { 805 SPDK_ERRLOG("portal_grp_register failed\n"); 806 } 807 808 out: 809 if (rc == 0) { 810 spdk_jsonrpc_send_bool_response(request, true); 811 } else { 812 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 813 814 if (pg != NULL) { 815 iscsi_portal_grp_release(pg); 816 } 817 } 818 free_rpc_portal_group(&req); 819 } 820 SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 821 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_portal_group, add_portal_group) 822 823 struct rpc_iscsi_delete_portal_group { 824 int32_t tag; 825 }; 826 827 static const struct spdk_json_object_decoder rpc_iscsi_delete_portal_group_decoders[] = { 828 {"tag", offsetof(struct rpc_iscsi_delete_portal_group, tag), spdk_json_decode_int32}, 829 }; 830 831 static void 832 rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 833 const struct spdk_json_val *params) 834 { 835 struct rpc_iscsi_delete_portal_group req = {}; 836 struct spdk_iscsi_portal_grp *pg; 837 838 if (spdk_json_decode_object(params, rpc_iscsi_delete_portal_group_decoders, 839 SPDK_COUNTOF(rpc_iscsi_delete_portal_group_decoders), 840 &req)) { 841 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 842 goto invalid; 843 } 844 845 pg = iscsi_portal_grp_unregister(req.tag); 846 if (!pg) { 847 goto invalid; 848 } 849 850 iscsi_tgt_node_delete_map(pg, NULL); 851 iscsi_portal_grp_release(pg); 852 853 spdk_jsonrpc_send_bool_response(request, true); 854 return; 855 856 invalid: 857 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 858 } 859 SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 860 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_portal_group, delete_portal_group) 861 862 struct rpc_portal_group_auth { 863 int32_t tag; 864 bool disable_chap; 865 bool require_chap; 866 bool mutual_chap; 867 int32_t chap_group; 868 }; 869 870 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 871 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 872 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 873 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 874 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 875 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 876 }; 877 878 static void 879 rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 880 const struct spdk_json_val *params) 881 { 882 struct rpc_portal_group_auth req = {}; 883 struct spdk_iscsi_portal_grp *pg; 884 int rc; 885 886 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 887 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 888 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 889 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 890 "Invalid parameters"); 891 return; 892 } 893 894 pthread_mutex_lock(&g_iscsi.mutex); 895 896 pg = iscsi_portal_grp_find_by_tag(req.tag); 897 if (pg == NULL) { 898 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 899 "Could not find portal group %d", req.tag); 900 goto exit; 901 } 902 903 rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 904 req.mutual_chap, req.chap_group); 905 if (rc < 0) { 906 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 907 "Invalid combination of auth params"); 908 goto exit; 909 } 910 911 pthread_mutex_unlock(&g_iscsi.mutex); 912 913 spdk_jsonrpc_send_bool_response(request, true); 914 return; 915 916 exit: 917 pthread_mutex_unlock(&g_iscsi.mutex); 918 } 919 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth, 920 SPDK_RPC_RUNTIME) 921 922 struct rpc_iscsi_get_connections_ctx { 923 struct spdk_jsonrpc_request *request; 924 struct spdk_json_write_ctx *w; 925 }; 926 927 static void 928 _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 929 { 930 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 931 932 spdk_json_write_array_end(ctx->w); 933 spdk_jsonrpc_end_result(ctx->request, ctx->w); 934 935 free(ctx); 936 } 937 938 static void 939 _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 940 { 941 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 942 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 943 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 944 struct spdk_iscsi_conn *conn; 945 946 STAILQ_FOREACH(conn, &pg->connections, pg_link) { 947 iscsi_conn_info_json(ctx->w, conn); 948 } 949 950 spdk_for_each_channel_continue(i, 0); 951 } 952 953 static void 954 rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 955 const struct spdk_json_val *params) 956 { 957 struct rpc_iscsi_get_connections_ctx *ctx; 958 959 if (params != NULL) { 960 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 961 "iscsi_get_connections requires no parameters"); 962 return; 963 } 964 965 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 966 if (ctx == NULL) { 967 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 968 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 969 return; 970 } 971 972 ctx->request = request; 973 ctx->w = spdk_jsonrpc_begin_result(request); 974 975 spdk_json_write_array_begin(ctx->w); 976 977 spdk_for_each_channel(&g_iscsi, 978 _rpc_iscsi_get_connections, 979 ctx, 980 _rpc_iscsi_get_connections_done); 981 } 982 SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 983 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_connections, get_iscsi_connections) 984 985 struct rpc_target_lun { 986 char *name; 987 char *bdev_name; 988 int32_t lun_id; 989 }; 990 991 static void 992 free_rpc_target_lun(struct rpc_target_lun *req) 993 { 994 free(req->name); 995 free(req->bdev_name); 996 } 997 998 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 999 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1000 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1001 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1002 }; 1003 1004 static void 1005 rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1006 const struct spdk_json_val *params) 1007 { 1008 struct rpc_target_lun req = {}; 1009 struct spdk_iscsi_tgt_node *target; 1010 int rc; 1011 1012 req.lun_id = -1; 1013 1014 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1015 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1016 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1017 goto invalid; 1018 } 1019 1020 target = iscsi_find_tgt_node(req.name); 1021 if (target == NULL) { 1022 SPDK_ERRLOG("target is not found\n"); 1023 goto invalid; 1024 } 1025 1026 rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1027 if (rc < 0) { 1028 SPDK_ERRLOG("add lun failed\n"); 1029 goto invalid; 1030 } 1031 1032 free_rpc_target_lun(&req); 1033 1034 spdk_jsonrpc_send_bool_response(request, true); 1035 return; 1036 1037 invalid: 1038 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1039 "Invalid parameters"); 1040 free_rpc_target_lun(&req); 1041 } 1042 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1043 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_lun, target_node_add_lun) 1044 1045 struct rpc_target_auth { 1046 char *name; 1047 bool disable_chap; 1048 bool require_chap; 1049 bool mutual_chap; 1050 int32_t chap_group; 1051 }; 1052 1053 static void 1054 free_rpc_target_auth(struct rpc_target_auth *req) 1055 { 1056 free(req->name); 1057 } 1058 1059 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1060 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1061 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1062 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1063 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1064 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1065 }; 1066 1067 static void 1068 rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1069 const struct spdk_json_val *params) 1070 { 1071 struct rpc_target_auth req = {}; 1072 struct spdk_iscsi_tgt_node *target; 1073 int rc; 1074 1075 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1076 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1077 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1078 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1079 "Invalid parameters"); 1080 goto exit; 1081 } 1082 1083 target = iscsi_find_tgt_node(req.name); 1084 if (target == NULL) { 1085 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1086 "Could not find target %s", req.name); 1087 goto exit; 1088 } 1089 1090 rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1091 req.mutual_chap, req.chap_group); 1092 if (rc < 0) { 1093 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1094 "Invalid combination of auth params"); 1095 goto exit; 1096 } 1097 1098 free_rpc_target_auth(&req); 1099 1100 spdk_jsonrpc_send_bool_response(request, true); 1101 return; 1102 1103 exit: 1104 free_rpc_target_auth(&req); 1105 } 1106 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth, 1107 SPDK_RPC_RUNTIME) 1108 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_set_auth, set_iscsi_target_node_auth) 1109 1110 struct rpc_target_redirect { 1111 char *name; 1112 int32_t pg_tag; 1113 char *redirect_host; 1114 char *redirect_port; 1115 }; 1116 1117 static void 1118 free_rpc_target_redirect(struct rpc_target_redirect *req) 1119 { 1120 free(req->name); 1121 free(req->redirect_host); 1122 free(req->redirect_port); 1123 } 1124 1125 static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = { 1126 {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string}, 1127 {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32}, 1128 {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true}, 1129 {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true}, 1130 }; 1131 1132 static void 1133 rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request, 1134 const struct spdk_json_val *params) 1135 { 1136 struct rpc_target_redirect req = {}; 1137 struct spdk_iscsi_tgt_node *target; 1138 int rc; 1139 1140 if (spdk_json_decode_object(params, rpc_target_redirect_decoders, 1141 SPDK_COUNTOF(rpc_target_redirect_decoders), 1142 &req)) { 1143 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1144 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1145 "Invalid parameters"); 1146 free_rpc_target_redirect(&req); 1147 return; 1148 } 1149 1150 target = iscsi_find_tgt_node(req.name); 1151 if (target == NULL) { 1152 SPDK_ERRLOG("target %s is not found\n", req.name); 1153 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1154 "Target %s is not found", req.name); 1155 free_rpc_target_redirect(&req); 1156 return; 1157 } 1158 1159 rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port); 1160 if (rc != 0) { 1161 SPDK_ERRLOG("failed to redirect target %s\n", req.name); 1162 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1163 "Failed to redirect target %s, (%d): %s", 1164 req.name, rc, spdk_strerror(-rc)); 1165 free_rpc_target_redirect(&req); 1166 return; 1167 } 1168 1169 free_rpc_target_redirect(&req); 1170 1171 spdk_jsonrpc_send_bool_response(request, true); 1172 } 1173 SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect, 1174 SPDK_RPC_RUNTIME) 1175 1176 struct rpc_target_logout { 1177 char *name; 1178 int32_t pg_tag; 1179 }; 1180 1181 static void 1182 free_rpc_target_logout(struct rpc_target_logout *req) 1183 { 1184 free(req->name); 1185 } 1186 1187 static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = { 1188 {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string}, 1189 {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true}, 1190 }; 1191 1192 static void 1193 rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request, 1194 const struct spdk_json_val *params) 1195 { 1196 struct rpc_target_logout req = {}; 1197 struct spdk_iscsi_tgt_node *target; 1198 1199 /* If pg_tag is omitted, request all connections to the specified target 1200 * to logout. 1201 */ 1202 req.pg_tag = -1; 1203 1204 if (spdk_json_decode_object(params, rpc_target_logout_decoders, 1205 SPDK_COUNTOF(rpc_target_logout_decoders), 1206 &req)) { 1207 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1208 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1209 "Invalid parameters"); 1210 free_rpc_target_logout(&req); 1211 return; 1212 } 1213 1214 target = iscsi_find_tgt_node(req.name); 1215 if (target == NULL) { 1216 SPDK_ERRLOG("target %s is not found\n", req.name); 1217 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1218 "Target %s is not found", req.name); 1219 free_rpc_target_logout(&req); 1220 return; 1221 } 1222 1223 iscsi_conns_request_logout(target, req.pg_tag); 1224 1225 free_rpc_target_logout(&req); 1226 1227 spdk_jsonrpc_send_bool_response(request, true); 1228 } 1229 SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout, 1230 SPDK_RPC_RUNTIME) 1231 1232 static void 1233 rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1234 const struct spdk_json_val *params) 1235 { 1236 struct spdk_json_write_ctx *w; 1237 1238 if (params != NULL) { 1239 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1240 "iscsi_get_options requires no parameters"); 1241 return; 1242 } 1243 1244 w = spdk_jsonrpc_begin_result(request); 1245 iscsi_opts_info_json(w); 1246 1247 spdk_jsonrpc_end_result(request, w); 1248 } 1249 SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1250 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_options, get_iscsi_global_params) 1251 1252 struct rpc_discovery_auth { 1253 bool disable_chap; 1254 bool require_chap; 1255 bool mutual_chap; 1256 int32_t chap_group; 1257 }; 1258 1259 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1260 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1261 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1262 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1263 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1264 }; 1265 1266 static void 1267 rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1268 const struct spdk_json_val *params) 1269 { 1270 struct rpc_discovery_auth req = {}; 1271 int rc; 1272 1273 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1274 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1275 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1276 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1277 "Invalid parameters"); 1278 return; 1279 } 1280 1281 rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1282 req.mutual_chap, req.chap_group); 1283 if (rc < 0) { 1284 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1285 "Invalid combination of CHAP params"); 1286 return; 1287 } 1288 1289 spdk_jsonrpc_send_bool_response(request, true); 1290 } 1291 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1292 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_discovery_auth, set_iscsi_discovery_auth) 1293 1294 #define MAX_AUTH_SECRETS 64 1295 1296 struct rpc_auth_secret { 1297 char *user; 1298 char *secret; 1299 char *muser; 1300 char *msecret; 1301 }; 1302 1303 static void 1304 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1305 { 1306 free(_secret->user); 1307 free(_secret->secret); 1308 free(_secret->muser); 1309 free(_secret->msecret); 1310 } 1311 1312 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1313 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1314 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1315 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1316 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1317 }; 1318 1319 static int 1320 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1321 { 1322 struct rpc_auth_secret *_secret = out; 1323 1324 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1325 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1326 } 1327 1328 struct rpc_auth_secrets { 1329 size_t num_secret; 1330 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1331 }; 1332 1333 static void 1334 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1335 { 1336 size_t i; 1337 1338 for (i = 0; i < secrets->num_secret; i++) { 1339 free_rpc_auth_secret(&secrets->secrets[i]); 1340 } 1341 } 1342 1343 static int 1344 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1345 { 1346 struct rpc_auth_secrets *secrets = out; 1347 1348 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1349 MAX_AUTH_SECRETS, &secrets->num_secret, 1350 sizeof(struct rpc_auth_secret)); 1351 } 1352 1353 struct rpc_auth_group { 1354 int32_t tag; 1355 struct rpc_auth_secrets secrets; 1356 }; 1357 1358 static void 1359 free_rpc_auth_group(struct rpc_auth_group *group) 1360 { 1361 free_rpc_auth_secrets(&group->secrets); 1362 } 1363 1364 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1365 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1366 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1367 }; 1368 1369 static void 1370 rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1371 const struct spdk_json_val *params) 1372 { 1373 struct rpc_auth_group req = {}; 1374 struct rpc_auth_secret *_secret; 1375 struct spdk_iscsi_auth_group *group = NULL; 1376 int rc; 1377 size_t i; 1378 1379 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1380 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1381 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1382 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1383 "Invalid parameters"); 1384 free_rpc_auth_group(&req); 1385 return; 1386 } 1387 1388 pthread_mutex_lock(&g_iscsi.mutex); 1389 1390 rc = iscsi_add_auth_group(req.tag, &group); 1391 if (rc != 0) { 1392 pthread_mutex_unlock(&g_iscsi.mutex); 1393 1394 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1395 "Could not add auth group (%d), %s", 1396 req.tag, spdk_strerror(-rc)); 1397 free_rpc_auth_group(&req); 1398 return; 1399 } 1400 1401 for (i = 0; i < req.secrets.num_secret; i++) { 1402 _secret = &req.secrets.secrets[i]; 1403 rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1404 _secret->muser, _secret->msecret); 1405 if (rc != 0) { 1406 iscsi_delete_auth_group(group); 1407 pthread_mutex_unlock(&g_iscsi.mutex); 1408 1409 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1410 "Could not add secret to auth group (%d), %s", 1411 req.tag, spdk_strerror(-rc)); 1412 free_rpc_auth_group(&req); 1413 return; 1414 } 1415 } 1416 1417 pthread_mutex_unlock(&g_iscsi.mutex); 1418 1419 free_rpc_auth_group(&req); 1420 1421 spdk_jsonrpc_send_bool_response(request, true); 1422 } 1423 SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1424 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_auth_group, add_iscsi_auth_group) 1425 1426 struct rpc_delete_auth_group { 1427 int32_t tag; 1428 }; 1429 1430 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1431 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1432 }; 1433 1434 static void 1435 rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1436 const struct spdk_json_val *params) 1437 { 1438 struct rpc_delete_auth_group req = {}; 1439 struct spdk_iscsi_auth_group *group; 1440 1441 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1442 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1443 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1444 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1445 "Invalid parameters"); 1446 return; 1447 } 1448 1449 pthread_mutex_lock(&g_iscsi.mutex); 1450 1451 group = iscsi_find_auth_group_by_tag(req.tag); 1452 if (group == NULL) { 1453 pthread_mutex_unlock(&g_iscsi.mutex); 1454 1455 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1456 "Could not find auth group (%d)", req.tag); 1457 return; 1458 } 1459 1460 iscsi_delete_auth_group(group); 1461 1462 pthread_mutex_unlock(&g_iscsi.mutex); 1463 1464 spdk_jsonrpc_send_bool_response(request, true); 1465 } 1466 SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1467 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_auth_group, delete_iscsi_auth_group) 1468 1469 struct rpc_add_auth_secret { 1470 int32_t tag; 1471 char *user; 1472 char *secret; 1473 char *muser; 1474 char *msecret; 1475 }; 1476 1477 static void 1478 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1479 { 1480 free(_secret->user); 1481 free(_secret->secret); 1482 free(_secret->muser); 1483 free(_secret->msecret); 1484 } 1485 1486 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1487 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1488 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1489 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1490 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1491 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1492 }; 1493 1494 static void 1495 rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1496 const struct spdk_json_val *params) 1497 { 1498 struct rpc_add_auth_secret req = {}; 1499 struct spdk_iscsi_auth_group *group; 1500 int rc; 1501 1502 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1503 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1504 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1505 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1506 "Invalid parameters"); 1507 free_rpc_add_auth_secret(&req); 1508 return; 1509 } 1510 1511 pthread_mutex_lock(&g_iscsi.mutex); 1512 1513 group = iscsi_find_auth_group_by_tag(req.tag); 1514 if (group == NULL) { 1515 pthread_mutex_unlock(&g_iscsi.mutex); 1516 1517 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1518 "Could not find auth group (%d)", req.tag); 1519 free_rpc_add_auth_secret(&req); 1520 return; 1521 } 1522 1523 rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1524 if (rc != 0) { 1525 pthread_mutex_unlock(&g_iscsi.mutex); 1526 1527 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1528 "Could not add secret to auth group (%d), %s", 1529 req.tag, spdk_strerror(-rc)); 1530 free_rpc_add_auth_secret(&req); 1531 return; 1532 } 1533 1534 pthread_mutex_unlock(&g_iscsi.mutex); 1535 1536 free_rpc_add_auth_secret(&req); 1537 1538 spdk_jsonrpc_send_bool_response(request, true); 1539 } 1540 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret, 1541 SPDK_RPC_RUNTIME) 1542 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_add_secret, add_secret_to_iscsi_auth_group) 1543 1544 1545 struct rpc_remove_auth_secret { 1546 int32_t tag; 1547 char *user; 1548 }; 1549 1550 static void 1551 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1552 { 1553 free(_secret->user); 1554 } 1555 1556 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1557 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1558 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1559 }; 1560 1561 static void 1562 rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1563 const struct spdk_json_val *params) 1564 { 1565 struct rpc_remove_auth_secret req = {}; 1566 struct spdk_iscsi_auth_group *group; 1567 int rc; 1568 1569 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1570 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1571 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1572 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1573 "Invalid parameters"); 1574 free_rpc_remove_auth_secret(&req); 1575 return; 1576 } 1577 1578 pthread_mutex_lock(&g_iscsi.mutex); 1579 1580 group = iscsi_find_auth_group_by_tag(req.tag); 1581 if (group == NULL) { 1582 pthread_mutex_unlock(&g_iscsi.mutex); 1583 1584 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1585 "Could not find auth group (%d)", req.tag); 1586 free_rpc_remove_auth_secret(&req); 1587 return; 1588 } 1589 1590 rc = iscsi_auth_group_delete_secret(group, req.user); 1591 if (rc != 0) { 1592 pthread_mutex_unlock(&g_iscsi.mutex); 1593 1594 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1595 "Could not delete secret from CHAP group (%d), %s", 1596 req.tag, spdk_strerror(-rc)); 1597 free_rpc_remove_auth_secret(&req); 1598 return; 1599 } 1600 1601 pthread_mutex_unlock(&g_iscsi.mutex); 1602 1603 free_rpc_remove_auth_secret(&req); 1604 1605 spdk_jsonrpc_send_bool_response(request, true); 1606 } 1607 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1608 rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1609 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_remove_secret, 1610 delete_secret_from_iscsi_auth_group) 1611 1612 static void 1613 rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1614 const struct spdk_json_val *params) 1615 { 1616 struct spdk_json_write_ctx *w; 1617 1618 if (params != NULL) { 1619 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1620 "iscsi_get_auth_groups requires no parameters"); 1621 return; 1622 } 1623 1624 w = spdk_jsonrpc_begin_result(request); 1625 spdk_json_write_array_begin(w); 1626 iscsi_auth_groups_info_json(w); 1627 spdk_json_write_array_end(w); 1628 1629 spdk_jsonrpc_end_result(request, w); 1630 } 1631 SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1632 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_auth_groups, get_iscsi_auth_groups) 1633 1634 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1635 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1636 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1637 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1638 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1639 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1640 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1641 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1642 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1643 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1644 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1645 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1646 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1647 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1648 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1649 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1650 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1651 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1652 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1653 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1654 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1655 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1656 {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true}, 1657 {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true}, 1658 }; 1659 1660 static void 1661 rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1662 const struct spdk_json_val *params) 1663 { 1664 struct spdk_iscsi_opts *opts; 1665 1666 if (g_spdk_iscsi_opts != NULL) { 1667 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1668 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1669 "Must not call more than once"); 1670 return; 1671 } 1672 1673 opts = iscsi_opts_alloc(); 1674 if (opts == NULL) { 1675 SPDK_ERRLOG("iscsi_opts_alloc() failed.\n"); 1676 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1677 "Out of memory"); 1678 return; 1679 } 1680 1681 if (params != NULL) { 1682 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1683 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1684 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1685 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1686 "Invalid parameters"); 1687 iscsi_opts_free(opts); 1688 return; 1689 } 1690 } 1691 1692 g_spdk_iscsi_opts = iscsi_opts_copy(opts); 1693 iscsi_opts_free(opts); 1694 1695 if (g_spdk_iscsi_opts == NULL) { 1696 SPDK_ERRLOG("iscsi_opts_copy() failed\n"); 1697 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1698 "Out of memory"); 1699 return; 1700 } 1701 1702 spdk_jsonrpc_send_bool_response(request, true); 1703 } 1704 SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1705 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_options, set_iscsi_options) 1706