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