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 bool wait; 710 }; 711 712 static void 713 free_rpc_portal(struct rpc_portal *portal) 714 { 715 free(portal->host); 716 free(portal->port); 717 } 718 719 static void 720 free_rpc_portal_list(struct rpc_portal_list *pl) 721 { 722 size_t i; 723 724 for (i = 0; i < pl->num_portals; i++) { 725 free_rpc_portal(&pl->portals[i]); 726 } 727 pl->num_portals = 0; 728 } 729 730 static void 731 free_rpc_portal_group(struct rpc_portal_group *pg) 732 { 733 free_rpc_portal_list(&pg->portal_list); 734 } 735 736 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 737 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 738 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 739 }; 740 741 static int 742 decode_rpc_portal(const struct spdk_json_val *val, void *out) 743 { 744 struct rpc_portal *portal = out; 745 746 return spdk_json_decode_object(val, rpc_portal_decoders, 747 SPDK_COUNTOF(rpc_portal_decoders), 748 portal); 749 } 750 751 static int 752 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 753 { 754 struct rpc_portal_list *list = out; 755 756 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 757 sizeof(struct rpc_portal)); 758 } 759 760 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 761 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 762 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 763 {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true}, 764 {"wait", offsetof(struct rpc_portal_group, wait), spdk_json_decode_bool, true}, 765 }; 766 767 static void 768 rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 769 const struct spdk_json_val *params) 770 { 771 struct rpc_portal_group req = {}; 772 struct spdk_iscsi_portal_grp *pg = NULL; 773 struct spdk_iscsi_portal *portal; 774 size_t i = 0; 775 int rc = -1; 776 777 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 778 SPDK_COUNTOF(rpc_portal_group_decoders), 779 &req)) { 780 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 781 goto out; 782 } 783 784 pg = iscsi_portal_grp_create(req.tag, req.is_private); 785 if (pg == NULL) { 786 SPDK_ERRLOG("portal_grp_create failed\n"); 787 goto out; 788 } 789 for (i = 0; i < req.portal_list.num_portals; i++) { 790 portal = iscsi_portal_create(req.portal_list.portals[i].host, 791 req.portal_list.portals[i].port); 792 if (portal == NULL) { 793 SPDK_ERRLOG("portal_create failed\n"); 794 goto out; 795 } 796 iscsi_portal_grp_add_portal(pg, portal); 797 } 798 799 rc = iscsi_portal_grp_open(pg, req.wait); 800 if (rc != 0) { 801 SPDK_ERRLOG("portal_grp_open failed\n"); 802 goto out; 803 } 804 805 rc = iscsi_portal_grp_register(pg); 806 if (rc != 0) { 807 SPDK_ERRLOG("portal_grp_register failed\n"); 808 } 809 810 out: 811 if (rc == 0) { 812 spdk_jsonrpc_send_bool_response(request, true); 813 } else { 814 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 815 816 if (pg != NULL) { 817 iscsi_portal_grp_release(pg); 818 } 819 } 820 free_rpc_portal_group(&req); 821 } 822 SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 823 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_portal_group, add_portal_group) 824 825 struct rpc_iscsi_change_portal_group { 826 int32_t tag; 827 }; 828 829 static const struct spdk_json_object_decoder rpc_iscsi_change_portal_group_decoders[] = { 830 {"tag", offsetof(struct rpc_iscsi_change_portal_group, tag), spdk_json_decode_int32}, 831 }; 832 833 typedef int (*iscsi_change_portal_grp_fn)(int pg_tag); 834 835 static void 836 _rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request *request, 837 const struct spdk_json_val *params, 838 iscsi_change_portal_grp_fn fn) 839 { 840 struct rpc_iscsi_change_portal_group req = {}; 841 int rc; 842 843 if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders, 844 SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders), 845 &req)) { 846 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 847 goto invalid; 848 } 849 850 rc = fn(req.tag); 851 if (rc != 0) { 852 goto invalid; 853 } 854 855 spdk_jsonrpc_send_bool_response(request, true); 856 return; 857 858 invalid: 859 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 860 } 861 862 static int 863 _rpc_iscsi_delete_portal_group(int pg_tag) 864 { 865 struct spdk_iscsi_portal_grp *pg; 866 867 pg = iscsi_portal_grp_unregister(pg_tag); 868 if (!pg) { 869 return -ENODEV; 870 } 871 872 iscsi_tgt_node_delete_map(pg, NULL); 873 iscsi_portal_grp_release(pg); 874 return 0; 875 } 876 877 static void 878 rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 879 const struct spdk_json_val *params) 880 { 881 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group); 882 } 883 SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 884 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_portal_group, delete_portal_group) 885 886 static int 887 _rpc_iscsi_start_portal_group(int pg_tag) 888 { 889 struct spdk_iscsi_portal_grp *pg; 890 891 pg = iscsi_portal_grp_find_by_tag(pg_tag); 892 if (!pg) { 893 return -ENODEV; 894 } 895 896 iscsi_portal_grp_resume(pg); 897 return 0; 898 } 899 900 static void 901 rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request, 902 const struct spdk_json_val *params) 903 { 904 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group); 905 } 906 SPDK_RPC_REGISTER("iscsi_start_portal_group", rpc_iscsi_start_portal_group, SPDK_RPC_RUNTIME) 907 908 struct rpc_portal_group_auth { 909 int32_t tag; 910 bool disable_chap; 911 bool require_chap; 912 bool mutual_chap; 913 int32_t chap_group; 914 }; 915 916 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 917 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 918 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 919 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 920 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 921 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 922 }; 923 924 static void 925 rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 926 const struct spdk_json_val *params) 927 { 928 struct rpc_portal_group_auth req = {}; 929 struct spdk_iscsi_portal_grp *pg; 930 int rc; 931 932 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 933 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 934 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 935 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 936 "Invalid parameters"); 937 return; 938 } 939 940 pthread_mutex_lock(&g_iscsi.mutex); 941 942 pg = iscsi_portal_grp_find_by_tag(req.tag); 943 if (pg == NULL) { 944 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 945 "Could not find portal group %d", req.tag); 946 goto exit; 947 } 948 949 rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 950 req.mutual_chap, req.chap_group); 951 if (rc < 0) { 952 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 953 "Invalid combination of auth params"); 954 goto exit; 955 } 956 957 pthread_mutex_unlock(&g_iscsi.mutex); 958 959 spdk_jsonrpc_send_bool_response(request, true); 960 return; 961 962 exit: 963 pthread_mutex_unlock(&g_iscsi.mutex); 964 } 965 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth, 966 SPDK_RPC_RUNTIME) 967 968 struct rpc_iscsi_get_connections_ctx { 969 struct spdk_jsonrpc_request *request; 970 struct spdk_json_write_ctx *w; 971 }; 972 973 static void 974 _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 975 { 976 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 977 978 spdk_json_write_array_end(ctx->w); 979 spdk_jsonrpc_end_result(ctx->request, ctx->w); 980 981 free(ctx); 982 } 983 984 static void 985 _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 986 { 987 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 988 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 989 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 990 struct spdk_iscsi_conn *conn; 991 992 STAILQ_FOREACH(conn, &pg->connections, pg_link) { 993 iscsi_conn_info_json(ctx->w, conn); 994 } 995 996 spdk_for_each_channel_continue(i, 0); 997 } 998 999 static void 1000 rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 1001 const struct spdk_json_val *params) 1002 { 1003 struct rpc_iscsi_get_connections_ctx *ctx; 1004 1005 if (params != NULL) { 1006 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1007 "iscsi_get_connections requires no parameters"); 1008 return; 1009 } 1010 1011 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 1012 if (ctx == NULL) { 1013 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 1014 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1015 return; 1016 } 1017 1018 ctx->request = request; 1019 ctx->w = spdk_jsonrpc_begin_result(request); 1020 1021 spdk_json_write_array_begin(ctx->w); 1022 1023 spdk_for_each_channel(&g_iscsi, 1024 _rpc_iscsi_get_connections, 1025 ctx, 1026 _rpc_iscsi_get_connections_done); 1027 } 1028 SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 1029 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_connections, get_iscsi_connections) 1030 1031 struct rpc_target_lun { 1032 char *name; 1033 char *bdev_name; 1034 int32_t lun_id; 1035 }; 1036 1037 static void 1038 free_rpc_target_lun(struct rpc_target_lun *req) 1039 { 1040 free(req->name); 1041 free(req->bdev_name); 1042 } 1043 1044 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1045 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1046 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1047 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1048 }; 1049 1050 static void 1051 rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1052 const struct spdk_json_val *params) 1053 { 1054 struct rpc_target_lun req = {}; 1055 struct spdk_iscsi_tgt_node *target; 1056 int rc; 1057 1058 req.lun_id = -1; 1059 1060 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1061 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1062 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1063 goto invalid; 1064 } 1065 1066 target = iscsi_find_tgt_node(req.name); 1067 if (target == NULL) { 1068 SPDK_ERRLOG("target is not found\n"); 1069 goto invalid; 1070 } 1071 1072 rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1073 if (rc < 0) { 1074 SPDK_ERRLOG("add lun failed\n"); 1075 goto invalid; 1076 } 1077 1078 free_rpc_target_lun(&req); 1079 1080 spdk_jsonrpc_send_bool_response(request, true); 1081 return; 1082 1083 invalid: 1084 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1085 "Invalid parameters"); 1086 free_rpc_target_lun(&req); 1087 } 1088 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1089 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_lun, target_node_add_lun) 1090 1091 struct rpc_target_auth { 1092 char *name; 1093 bool disable_chap; 1094 bool require_chap; 1095 bool mutual_chap; 1096 int32_t chap_group; 1097 }; 1098 1099 static void 1100 free_rpc_target_auth(struct rpc_target_auth *req) 1101 { 1102 free(req->name); 1103 } 1104 1105 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1106 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1107 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1108 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1109 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1110 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1111 }; 1112 1113 static void 1114 rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1115 const struct spdk_json_val *params) 1116 { 1117 struct rpc_target_auth req = {}; 1118 struct spdk_iscsi_tgt_node *target; 1119 int rc; 1120 1121 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1122 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1123 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1124 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1125 "Invalid parameters"); 1126 goto exit; 1127 } 1128 1129 target = iscsi_find_tgt_node(req.name); 1130 if (target == NULL) { 1131 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1132 "Could not find target %s", req.name); 1133 goto exit; 1134 } 1135 1136 rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1137 req.mutual_chap, req.chap_group); 1138 if (rc < 0) { 1139 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1140 "Invalid combination of auth params"); 1141 goto exit; 1142 } 1143 1144 free_rpc_target_auth(&req); 1145 1146 spdk_jsonrpc_send_bool_response(request, true); 1147 return; 1148 1149 exit: 1150 free_rpc_target_auth(&req); 1151 } 1152 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth, 1153 SPDK_RPC_RUNTIME) 1154 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_set_auth, set_iscsi_target_node_auth) 1155 1156 struct rpc_target_redirect { 1157 char *name; 1158 int32_t pg_tag; 1159 char *redirect_host; 1160 char *redirect_port; 1161 }; 1162 1163 static void 1164 free_rpc_target_redirect(struct rpc_target_redirect *req) 1165 { 1166 free(req->name); 1167 free(req->redirect_host); 1168 free(req->redirect_port); 1169 } 1170 1171 static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = { 1172 {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string}, 1173 {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32}, 1174 {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true}, 1175 {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true}, 1176 }; 1177 1178 static void 1179 rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request, 1180 const struct spdk_json_val *params) 1181 { 1182 struct rpc_target_redirect req = {}; 1183 struct spdk_iscsi_tgt_node *target; 1184 int rc; 1185 1186 if (spdk_json_decode_object(params, rpc_target_redirect_decoders, 1187 SPDK_COUNTOF(rpc_target_redirect_decoders), 1188 &req)) { 1189 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1190 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1191 "Invalid parameters"); 1192 free_rpc_target_redirect(&req); 1193 return; 1194 } 1195 1196 target = iscsi_find_tgt_node(req.name); 1197 if (target == NULL) { 1198 SPDK_ERRLOG("target %s is not found\n", req.name); 1199 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1200 "Target %s is not found", req.name); 1201 free_rpc_target_redirect(&req); 1202 return; 1203 } 1204 1205 rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port); 1206 if (rc != 0) { 1207 SPDK_ERRLOG("failed to redirect target %s\n", req.name); 1208 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1209 "Failed to redirect target %s, (%d): %s", 1210 req.name, rc, spdk_strerror(-rc)); 1211 free_rpc_target_redirect(&req); 1212 return; 1213 } 1214 1215 free_rpc_target_redirect(&req); 1216 1217 spdk_jsonrpc_send_bool_response(request, true); 1218 } 1219 SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect, 1220 SPDK_RPC_RUNTIME) 1221 1222 struct rpc_target_logout { 1223 char *name; 1224 int32_t pg_tag; 1225 }; 1226 1227 static void 1228 free_rpc_target_logout(struct rpc_target_logout *req) 1229 { 1230 free(req->name); 1231 } 1232 1233 static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = { 1234 {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string}, 1235 {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true}, 1236 }; 1237 1238 static void 1239 rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request, 1240 const struct spdk_json_val *params) 1241 { 1242 struct rpc_target_logout req = {}; 1243 struct spdk_iscsi_tgt_node *target; 1244 1245 /* If pg_tag is omitted, request all connections to the specified target 1246 * to logout. 1247 */ 1248 req.pg_tag = -1; 1249 1250 if (spdk_json_decode_object(params, rpc_target_logout_decoders, 1251 SPDK_COUNTOF(rpc_target_logout_decoders), 1252 &req)) { 1253 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1254 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1255 "Invalid parameters"); 1256 free_rpc_target_logout(&req); 1257 return; 1258 } 1259 1260 target = iscsi_find_tgt_node(req.name); 1261 if (target == NULL) { 1262 SPDK_ERRLOG("target %s is not found\n", req.name); 1263 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1264 "Target %s is not found", req.name); 1265 free_rpc_target_logout(&req); 1266 return; 1267 } 1268 1269 iscsi_conns_request_logout(target, req.pg_tag); 1270 1271 free_rpc_target_logout(&req); 1272 1273 spdk_jsonrpc_send_bool_response(request, true); 1274 } 1275 SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout, 1276 SPDK_RPC_RUNTIME) 1277 1278 static void 1279 rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1280 const struct spdk_json_val *params) 1281 { 1282 struct spdk_json_write_ctx *w; 1283 1284 if (params != NULL) { 1285 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1286 "iscsi_get_options requires no parameters"); 1287 return; 1288 } 1289 1290 w = spdk_jsonrpc_begin_result(request); 1291 iscsi_opts_info_json(w); 1292 1293 spdk_jsonrpc_end_result(request, w); 1294 } 1295 SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1296 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_options, get_iscsi_global_params) 1297 1298 struct rpc_discovery_auth { 1299 bool disable_chap; 1300 bool require_chap; 1301 bool mutual_chap; 1302 int32_t chap_group; 1303 }; 1304 1305 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1306 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1307 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1308 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1309 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1310 }; 1311 1312 static void 1313 rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1314 const struct spdk_json_val *params) 1315 { 1316 struct rpc_discovery_auth req = {}; 1317 int rc; 1318 1319 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1320 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1321 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1322 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1323 "Invalid parameters"); 1324 return; 1325 } 1326 1327 rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1328 req.mutual_chap, req.chap_group); 1329 if (rc < 0) { 1330 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1331 "Invalid combination of CHAP params"); 1332 return; 1333 } 1334 1335 spdk_jsonrpc_send_bool_response(request, true); 1336 } 1337 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1338 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_discovery_auth, set_iscsi_discovery_auth) 1339 1340 #define MAX_AUTH_SECRETS 64 1341 1342 struct rpc_auth_secret { 1343 char *user; 1344 char *secret; 1345 char *muser; 1346 char *msecret; 1347 }; 1348 1349 static void 1350 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1351 { 1352 free(_secret->user); 1353 free(_secret->secret); 1354 free(_secret->muser); 1355 free(_secret->msecret); 1356 } 1357 1358 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1359 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1360 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1361 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1362 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1363 }; 1364 1365 static int 1366 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1367 { 1368 struct rpc_auth_secret *_secret = out; 1369 1370 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1371 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1372 } 1373 1374 struct rpc_auth_secrets { 1375 size_t num_secret; 1376 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1377 }; 1378 1379 static void 1380 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1381 { 1382 size_t i; 1383 1384 for (i = 0; i < secrets->num_secret; i++) { 1385 free_rpc_auth_secret(&secrets->secrets[i]); 1386 } 1387 } 1388 1389 static int 1390 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1391 { 1392 struct rpc_auth_secrets *secrets = out; 1393 1394 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1395 MAX_AUTH_SECRETS, &secrets->num_secret, 1396 sizeof(struct rpc_auth_secret)); 1397 } 1398 1399 struct rpc_auth_group { 1400 int32_t tag; 1401 struct rpc_auth_secrets secrets; 1402 }; 1403 1404 static void 1405 free_rpc_auth_group(struct rpc_auth_group *group) 1406 { 1407 free_rpc_auth_secrets(&group->secrets); 1408 } 1409 1410 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1411 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1412 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1413 }; 1414 1415 static void 1416 rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1417 const struct spdk_json_val *params) 1418 { 1419 struct rpc_auth_group req = {}; 1420 struct rpc_auth_secret *_secret; 1421 struct spdk_iscsi_auth_group *group = NULL; 1422 int rc; 1423 size_t i; 1424 1425 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1426 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1427 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1428 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1429 "Invalid parameters"); 1430 free_rpc_auth_group(&req); 1431 return; 1432 } 1433 1434 pthread_mutex_lock(&g_iscsi.mutex); 1435 1436 rc = iscsi_add_auth_group(req.tag, &group); 1437 if (rc != 0) { 1438 pthread_mutex_unlock(&g_iscsi.mutex); 1439 1440 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1441 "Could not add auth group (%d), %s", 1442 req.tag, spdk_strerror(-rc)); 1443 free_rpc_auth_group(&req); 1444 return; 1445 } 1446 1447 for (i = 0; i < req.secrets.num_secret; i++) { 1448 _secret = &req.secrets.secrets[i]; 1449 rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1450 _secret->muser, _secret->msecret); 1451 if (rc != 0) { 1452 iscsi_delete_auth_group(group); 1453 pthread_mutex_unlock(&g_iscsi.mutex); 1454 1455 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1456 "Could not add secret to auth group (%d), %s", 1457 req.tag, spdk_strerror(-rc)); 1458 free_rpc_auth_group(&req); 1459 return; 1460 } 1461 } 1462 1463 pthread_mutex_unlock(&g_iscsi.mutex); 1464 1465 free_rpc_auth_group(&req); 1466 1467 spdk_jsonrpc_send_bool_response(request, true); 1468 } 1469 SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1470 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_auth_group, add_iscsi_auth_group) 1471 1472 struct rpc_delete_auth_group { 1473 int32_t tag; 1474 }; 1475 1476 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1477 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1478 }; 1479 1480 static void 1481 rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1482 const struct spdk_json_val *params) 1483 { 1484 struct rpc_delete_auth_group req = {}; 1485 struct spdk_iscsi_auth_group *group; 1486 1487 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1488 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1489 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1490 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1491 "Invalid parameters"); 1492 return; 1493 } 1494 1495 pthread_mutex_lock(&g_iscsi.mutex); 1496 1497 group = iscsi_find_auth_group_by_tag(req.tag); 1498 if (group == NULL) { 1499 pthread_mutex_unlock(&g_iscsi.mutex); 1500 1501 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1502 "Could not find auth group (%d)", req.tag); 1503 return; 1504 } 1505 1506 iscsi_delete_auth_group(group); 1507 1508 pthread_mutex_unlock(&g_iscsi.mutex); 1509 1510 spdk_jsonrpc_send_bool_response(request, true); 1511 } 1512 SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1513 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_auth_group, delete_iscsi_auth_group) 1514 1515 struct rpc_add_auth_secret { 1516 int32_t tag; 1517 char *user; 1518 char *secret; 1519 char *muser; 1520 char *msecret; 1521 }; 1522 1523 static void 1524 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1525 { 1526 free(_secret->user); 1527 free(_secret->secret); 1528 free(_secret->muser); 1529 free(_secret->msecret); 1530 } 1531 1532 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1533 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1534 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1535 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1536 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1537 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1538 }; 1539 1540 static void 1541 rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1542 const struct spdk_json_val *params) 1543 { 1544 struct rpc_add_auth_secret req = {}; 1545 struct spdk_iscsi_auth_group *group; 1546 int rc; 1547 1548 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1549 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1550 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1551 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1552 "Invalid parameters"); 1553 free_rpc_add_auth_secret(&req); 1554 return; 1555 } 1556 1557 pthread_mutex_lock(&g_iscsi.mutex); 1558 1559 group = iscsi_find_auth_group_by_tag(req.tag); 1560 if (group == NULL) { 1561 pthread_mutex_unlock(&g_iscsi.mutex); 1562 1563 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1564 "Could not find auth group (%d)", req.tag); 1565 free_rpc_add_auth_secret(&req); 1566 return; 1567 } 1568 1569 rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1570 if (rc != 0) { 1571 pthread_mutex_unlock(&g_iscsi.mutex); 1572 1573 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1574 "Could not add secret to auth group (%d), %s", 1575 req.tag, spdk_strerror(-rc)); 1576 free_rpc_add_auth_secret(&req); 1577 return; 1578 } 1579 1580 pthread_mutex_unlock(&g_iscsi.mutex); 1581 1582 free_rpc_add_auth_secret(&req); 1583 1584 spdk_jsonrpc_send_bool_response(request, true); 1585 } 1586 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret, 1587 SPDK_RPC_RUNTIME) 1588 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_add_secret, add_secret_to_iscsi_auth_group) 1589 1590 1591 struct rpc_remove_auth_secret { 1592 int32_t tag; 1593 char *user; 1594 }; 1595 1596 static void 1597 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1598 { 1599 free(_secret->user); 1600 } 1601 1602 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1603 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1604 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1605 }; 1606 1607 static void 1608 rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1609 const struct spdk_json_val *params) 1610 { 1611 struct rpc_remove_auth_secret req = {}; 1612 struct spdk_iscsi_auth_group *group; 1613 int rc; 1614 1615 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1616 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1617 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1618 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1619 "Invalid parameters"); 1620 free_rpc_remove_auth_secret(&req); 1621 return; 1622 } 1623 1624 pthread_mutex_lock(&g_iscsi.mutex); 1625 1626 group = iscsi_find_auth_group_by_tag(req.tag); 1627 if (group == NULL) { 1628 pthread_mutex_unlock(&g_iscsi.mutex); 1629 1630 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1631 "Could not find auth group (%d)", req.tag); 1632 free_rpc_remove_auth_secret(&req); 1633 return; 1634 } 1635 1636 rc = iscsi_auth_group_delete_secret(group, req.user); 1637 if (rc != 0) { 1638 pthread_mutex_unlock(&g_iscsi.mutex); 1639 1640 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1641 "Could not delete secret from CHAP group (%d), %s", 1642 req.tag, spdk_strerror(-rc)); 1643 free_rpc_remove_auth_secret(&req); 1644 return; 1645 } 1646 1647 pthread_mutex_unlock(&g_iscsi.mutex); 1648 1649 free_rpc_remove_auth_secret(&req); 1650 1651 spdk_jsonrpc_send_bool_response(request, true); 1652 } 1653 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1654 rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1655 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_remove_secret, 1656 delete_secret_from_iscsi_auth_group) 1657 1658 static void 1659 rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1660 const struct spdk_json_val *params) 1661 { 1662 struct spdk_json_write_ctx *w; 1663 1664 if (params != NULL) { 1665 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1666 "iscsi_get_auth_groups requires no parameters"); 1667 return; 1668 } 1669 1670 w = spdk_jsonrpc_begin_result(request); 1671 spdk_json_write_array_begin(w); 1672 iscsi_auth_groups_info_json(w); 1673 spdk_json_write_array_end(w); 1674 1675 spdk_jsonrpc_end_result(request, w); 1676 } 1677 SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1678 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_auth_groups, get_iscsi_auth_groups) 1679 1680 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1681 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1682 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1683 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1684 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1685 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1686 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1687 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1688 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1689 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1690 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1691 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1692 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1693 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1694 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1695 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1696 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1697 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1698 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1699 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1700 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1701 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1702 {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true}, 1703 {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true}, 1704 }; 1705 1706 static void 1707 rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1708 const struct spdk_json_val *params) 1709 { 1710 struct spdk_iscsi_opts *opts; 1711 1712 if (g_spdk_iscsi_opts != NULL) { 1713 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1714 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1715 "Must not call more than once"); 1716 return; 1717 } 1718 1719 opts = iscsi_opts_alloc(); 1720 if (opts == NULL) { 1721 SPDK_ERRLOG("iscsi_opts_alloc() failed.\n"); 1722 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1723 "Out of memory"); 1724 return; 1725 } 1726 1727 if (params != NULL) { 1728 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1729 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1730 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1731 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1732 "Invalid parameters"); 1733 iscsi_opts_free(opts); 1734 return; 1735 } 1736 } 1737 1738 g_spdk_iscsi_opts = iscsi_opts_copy(opts); 1739 iscsi_opts_free(opts); 1740 1741 if (g_spdk_iscsi_opts == NULL) { 1742 SPDK_ERRLOG("iscsi_opts_copy() failed\n"); 1743 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1744 "Out of memory"); 1745 return; 1746 } 1747 1748 spdk_jsonrpc_send_bool_response(request, true); 1749 } 1750 SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1751 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_options, set_iscsi_options) 1752