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