1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "iscsi/iscsi.h" 36 #include "iscsi/conn.h" 37 #include "iscsi/tgt_node.h" 38 #include "iscsi/portal_grp.h" 39 #include "iscsi/init_grp.h" 40 41 #include "spdk/rpc.h" 42 #include "spdk/util.h" 43 #include "spdk/event.h" 44 #include "spdk/string.h" 45 #include "spdk_internal/log.h" 46 47 static void 48 spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_request *request, 49 const struct spdk_json_val *params) 50 { 51 struct spdk_json_write_ctx *w; 52 53 if (params != NULL) { 54 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 55 "get_initiator_groups requires no parameters"); 56 return; 57 } 58 59 w = spdk_jsonrpc_begin_result(request); 60 spdk_json_write_array_begin(w); 61 spdk_iscsi_init_grps_info_json(w); 62 spdk_json_write_array_end(w); 63 64 spdk_jsonrpc_end_result(request, w); 65 } 66 SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups, SPDK_RPC_RUNTIME) 67 68 struct rpc_initiator_list { 69 size_t num_initiators; 70 char *initiators[MAX_INITIATOR]; 71 }; 72 73 static int 74 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 75 { 76 struct rpc_initiator_list *list = out; 77 78 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 79 &list->num_initiators, sizeof(char *)); 80 } 81 82 static void 83 free_rpc_initiator_list(struct rpc_initiator_list *list) 84 { 85 size_t i; 86 87 for (i = 0; i < list->num_initiators; i++) { 88 free(list->initiators[i]); 89 } 90 } 91 92 struct rpc_netmask_list { 93 size_t num_netmasks; 94 char *netmasks[MAX_NETMASK]; 95 }; 96 97 static int 98 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 99 { 100 struct rpc_netmask_list *list = out; 101 102 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 103 &list->num_netmasks, sizeof(char *)); 104 } 105 106 static void 107 free_rpc_netmask_list(struct rpc_netmask_list *list) 108 { 109 size_t i; 110 111 for (i = 0; i < list->num_netmasks; i++) { 112 free(list->netmasks[i]); 113 } 114 } 115 116 struct rpc_initiator_group { 117 int32_t tag; 118 struct rpc_initiator_list initiator_list; 119 struct rpc_netmask_list netmask_list; 120 }; 121 122 static void 123 free_rpc_initiator_group(struct rpc_initiator_group *ig) 124 { 125 free_rpc_initiator_list(&ig->initiator_list); 126 free_rpc_netmask_list(&ig->netmask_list); 127 } 128 129 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 130 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 131 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 132 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 133 }; 134 135 static void 136 spdk_rpc_add_initiator_group(struct spdk_jsonrpc_request *request, 137 const struct spdk_json_val *params) 138 { 139 struct rpc_initiator_group req = {}; 140 struct spdk_json_write_ctx *w; 141 142 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 143 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 144 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 145 goto invalid; 146 } 147 148 if (req.initiator_list.num_initiators == 0 || 149 req.netmask_list.num_netmasks == 0) { 150 goto invalid; 151 } 152 153 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 154 req.initiator_list.num_initiators, 155 req.initiator_list.initiators, 156 req.netmask_list.num_netmasks, 157 req.netmask_list.netmasks)) { 158 SPDK_ERRLOG("create_from_initiator_list failed\n"); 159 goto invalid; 160 } 161 162 free_rpc_initiator_group(&req); 163 164 w = spdk_jsonrpc_begin_result(request); 165 spdk_json_write_bool(w, true); 166 spdk_jsonrpc_end_result(request, w); 167 return; 168 169 invalid: 170 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 171 free_rpc_initiator_group(&req); 172 } 173 SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group, SPDK_RPC_RUNTIME) 174 175 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 176 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 177 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 178 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 179 }; 180 181 static void 182 spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request, 183 const struct spdk_json_val *params) 184 { 185 struct rpc_initiator_group req = {}; 186 struct spdk_json_write_ctx *w; 187 188 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 189 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 190 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 191 goto invalid; 192 } 193 194 if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 195 req.initiator_list.num_initiators, 196 req.initiator_list.initiators, 197 req.netmask_list.num_netmasks, 198 req.netmask_list.netmasks)) { 199 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 200 goto invalid; 201 } 202 203 free_rpc_initiator_group(&req); 204 205 w = spdk_jsonrpc_begin_result(request); 206 spdk_json_write_bool(w, true); 207 spdk_jsonrpc_end_result(request, w); 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("add_initiators_to_initiator_group", 215 spdk_rpc_add_initiators_to_initiator_group, SPDK_RPC_RUNTIME) 216 217 static void 218 spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request, 219 const struct spdk_json_val *params) 220 { 221 struct rpc_initiator_group req = {}; 222 struct spdk_json_write_ctx *w; 223 224 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 225 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 226 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 227 goto invalid; 228 } 229 230 if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 231 req.initiator_list.num_initiators, 232 req.initiator_list.initiators, 233 req.netmask_list.num_netmasks, 234 req.netmask_list.netmasks)) { 235 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 236 goto invalid; 237 } 238 239 free_rpc_initiator_group(&req); 240 241 w = spdk_jsonrpc_begin_result(request); 242 spdk_json_write_bool(w, true); 243 spdk_jsonrpc_end_result(request, w); 244 return; 245 246 invalid: 247 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 248 free_rpc_initiator_group(&req); 249 } 250 SPDK_RPC_REGISTER("delete_initiators_from_initiator_group", 251 spdk_rpc_delete_initiators_from_initiator_group, SPDK_RPC_RUNTIME) 252 253 struct rpc_delete_initiator_group { 254 int32_t tag; 255 }; 256 257 static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = { 258 {"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32}, 259 }; 260 261 static void 262 spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_request *request, 263 const struct spdk_json_val *params) 264 { 265 struct rpc_delete_initiator_group req = {}; 266 struct spdk_json_write_ctx *w; 267 struct spdk_iscsi_init_grp *ig; 268 269 if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders, 270 SPDK_COUNTOF(rpc_delete_initiator_group_decoders), 271 &req)) { 272 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 273 goto invalid; 274 } 275 276 ig = spdk_iscsi_init_grp_unregister(req.tag); 277 if (!ig) { 278 goto invalid; 279 } 280 spdk_iscsi_tgt_node_delete_map(NULL, ig); 281 spdk_iscsi_init_grp_destroy(ig); 282 283 w = spdk_jsonrpc_begin_result(request); 284 spdk_json_write_bool(w, true); 285 spdk_jsonrpc_end_result(request, w); 286 return; 287 288 invalid: 289 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 290 } 291 SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group, SPDK_RPC_RUNTIME) 292 293 static void 294 spdk_rpc_get_target_nodes(struct spdk_jsonrpc_request *request, 295 const struct spdk_json_val *params) 296 { 297 struct spdk_json_write_ctx *w; 298 299 if (params != NULL) { 300 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 301 "get_target_nodes requires no parameters"); 302 return; 303 } 304 305 w = spdk_jsonrpc_begin_result(request); 306 spdk_json_write_array_begin(w); 307 spdk_iscsi_tgt_nodes_info_json(w); 308 spdk_json_write_array_end(w); 309 310 spdk_jsonrpc_end_result(request, w); 311 } 312 SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes, SPDK_RPC_RUNTIME) 313 314 struct rpc_pg_ig_map { 315 int32_t pg_tag; 316 int32_t ig_tag; 317 }; 318 319 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 320 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 321 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 322 }; 323 324 static int 325 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 326 { 327 struct rpc_pg_ig_map *pg_ig_map = out; 328 329 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 330 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 331 pg_ig_map); 332 } 333 334 struct rpc_pg_ig_maps { 335 size_t num_maps; 336 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 337 }; 338 339 static int 340 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 341 { 342 struct rpc_pg_ig_maps *pg_ig_maps = out; 343 344 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 345 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 346 sizeof(struct rpc_pg_ig_map)); 347 } 348 349 #define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64 350 351 struct rpc_lun { 352 char *bdev_name; 353 int32_t lun_id; 354 }; 355 356 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 357 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 358 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 359 }; 360 361 static int 362 decode_rpc_lun(const struct spdk_json_val *val, void *out) 363 { 364 struct rpc_lun *lun = out; 365 366 return spdk_json_decode_object(val, rpc_lun_decoders, 367 SPDK_COUNTOF(rpc_lun_decoders), lun); 368 } 369 370 struct rpc_luns { 371 size_t num_luns; 372 struct rpc_lun luns[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 373 }; 374 375 static int 376 decode_rpc_luns(const struct spdk_json_val *val, void *out) 377 { 378 struct rpc_luns *luns = out; 379 380 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 381 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 382 &luns->num_luns, sizeof(struct rpc_lun)); 383 } 384 385 static void 386 free_rpc_luns(struct rpc_luns *p) 387 { 388 size_t i; 389 390 for (i = 0; i < p->num_luns; i++) { 391 free(p->luns[i].bdev_name); 392 } 393 } 394 395 struct rpc_target_node { 396 char *name; 397 char *alias_name; 398 399 struct rpc_pg_ig_maps pg_ig_maps; 400 struct rpc_luns luns; 401 402 int32_t queue_depth; 403 bool disable_chap; 404 bool require_chap; 405 bool mutual_chap; 406 int32_t chap_group; 407 408 bool header_digest; 409 bool data_digest; 410 }; 411 412 static void 413 free_rpc_target_node(struct rpc_target_node *req) 414 { 415 free(req->name); 416 free(req->alias_name); 417 free_rpc_luns(&req->luns); 418 } 419 420 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 421 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 422 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 423 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 424 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 425 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 426 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 427 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 428 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 429 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 430 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 431 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 432 }; 433 434 static void 435 spdk_rpc_construct_target_node(struct spdk_jsonrpc_request *request, 436 const struct spdk_json_val *params) 437 { 438 struct rpc_target_node req = {}; 439 struct spdk_json_write_ctx *w; 440 struct spdk_iscsi_tgt_node *target; 441 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 442 char *bdev_names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 443 int32_t lun_ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 444 size_t i; 445 446 if (spdk_json_decode_object(params, rpc_target_node_decoders, 447 SPDK_COUNTOF(rpc_target_node_decoders), 448 &req)) { 449 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 450 goto invalid; 451 } 452 453 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 454 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 455 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 456 } 457 458 for (i = 0; i < req.luns.num_luns; i++) { 459 bdev_names[i] = req.luns.luns[i].bdev_name; 460 lun_ids[i] = req.luns.luns[i].lun_id; 461 } 462 463 /* 464 * Use default parameters in a few places: 465 * index = -1 : automatically pick an index for the new target node 466 * alias = NULL 467 */ 468 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 469 pg_tags, 470 ig_tags, 471 req.pg_ig_maps.num_maps, 472 (const char **)bdev_names, 473 lun_ids, 474 req.luns.num_luns, 475 req.queue_depth, 476 req.disable_chap, 477 req.require_chap, 478 req.mutual_chap, 479 req.chap_group, 480 req.header_digest, 481 req.data_digest); 482 483 if (target == NULL) { 484 goto invalid; 485 } 486 487 free_rpc_target_node(&req); 488 489 w = spdk_jsonrpc_begin_result(request); 490 spdk_json_write_bool(w, true); 491 spdk_jsonrpc_end_result(request, w); 492 return; 493 494 invalid: 495 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 496 free_rpc_target_node(&req); 497 } 498 SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node, SPDK_RPC_RUNTIME) 499 500 struct rpc_tgt_node_pg_ig_maps { 501 char *name; 502 struct rpc_pg_ig_maps pg_ig_maps; 503 }; 504 505 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 506 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 507 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 508 }; 509 510 static void 511 spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 512 const struct spdk_json_val *params) 513 { 514 struct rpc_tgt_node_pg_ig_maps req = {}; 515 struct spdk_json_write_ctx *w; 516 struct spdk_iscsi_tgt_node *target; 517 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 518 size_t i; 519 int rc; 520 521 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 522 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 523 &req)) { 524 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 525 goto invalid; 526 } 527 528 target = spdk_iscsi_find_tgt_node(req.name); 529 if (target == NULL) { 530 SPDK_ERRLOG("target is not found\n"); 531 goto invalid; 532 } 533 534 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 535 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 536 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 537 } 538 539 rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, pg_tags, ig_tags, 540 req.pg_ig_maps.num_maps); 541 if (rc < 0) { 542 SPDK_ERRLOG("add pg-ig maps failed\n"); 543 goto invalid; 544 } 545 546 free(req.name); 547 548 w = spdk_jsonrpc_begin_result(request); 549 spdk_json_write_bool(w, true); 550 spdk_jsonrpc_end_result(request, w); 551 return; 552 553 invalid: 554 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 555 "Invalid parameters"); 556 free(req.name); 557 } 558 SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps, SPDK_RPC_RUNTIME) 559 560 static void 561 spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request, 562 const struct spdk_json_val *params) 563 { 564 struct rpc_tgt_node_pg_ig_maps req = {}; 565 struct spdk_json_write_ctx *w; 566 struct spdk_iscsi_tgt_node *target; 567 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 568 size_t i; 569 int rc; 570 571 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 572 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 573 &req)) { 574 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 575 goto invalid; 576 } 577 578 target = spdk_iscsi_find_tgt_node(req.name); 579 if (target == NULL) { 580 SPDK_ERRLOG("target is not found\n"); 581 goto invalid; 582 } 583 584 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 585 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 586 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 587 } 588 589 rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, pg_tags, ig_tags, 590 req.pg_ig_maps.num_maps); 591 if (rc < 0) { 592 SPDK_ERRLOG("remove pg-ig maps failed\n"); 593 goto invalid; 594 } 595 596 free(req.name); 597 598 w = spdk_jsonrpc_begin_result(request); 599 spdk_json_write_bool(w, true); 600 spdk_jsonrpc_end_result(request, w); 601 return; 602 603 invalid: 604 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 605 "Invalid parameters"); 606 free(req.name); 607 } 608 SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps, SPDK_RPC_RUNTIME) 609 610 struct rpc_delete_target_node { 611 char *name; 612 }; 613 614 static void 615 free_rpc_delete_target_node(struct rpc_delete_target_node *r) 616 { 617 free(r->name); 618 } 619 620 static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = { 621 {"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string}, 622 }; 623 624 struct rpc_delete_target_node_ctx { 625 struct rpc_delete_target_node req; 626 struct spdk_jsonrpc_request *request; 627 }; 628 629 static void 630 rpc_delete_target_node_done(void *cb_arg, int rc) 631 { 632 struct rpc_delete_target_node_ctx *ctx = cb_arg; 633 struct spdk_json_write_ctx *w; 634 635 free_rpc_delete_target_node(&ctx->req); 636 637 w = spdk_jsonrpc_begin_result(ctx->request); 638 spdk_json_write_bool(w, rc == 0); 639 spdk_jsonrpc_end_result(ctx->request, w); 640 641 free(ctx); 642 } 643 644 static void 645 spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request, 646 const struct spdk_json_val *params) 647 { 648 struct rpc_delete_target_node_ctx *ctx; 649 650 ctx = calloc(1, sizeof(*ctx)); 651 if (!ctx) { 652 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 653 spdk_strerror(ENOMEM)); 654 return; 655 } 656 657 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 658 SPDK_COUNTOF(rpc_delete_target_node_decoders), 659 &ctx->req)) { 660 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 661 goto invalid; 662 } 663 664 if (ctx->req.name == NULL) { 665 SPDK_ERRLOG("missing name param\n"); 666 goto invalid; 667 } 668 669 ctx->request = request; 670 671 spdk_iscsi_shutdown_tgt_node_by_name(ctx->req.name, 672 rpc_delete_target_node_done, ctx); 673 return; 674 675 invalid: 676 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 677 free_rpc_delete_target_node(&ctx->req); 678 free(ctx); 679 } 680 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node, SPDK_RPC_RUNTIME) 681 682 static void 683 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request, 684 const struct spdk_json_val *params) 685 { 686 struct spdk_json_write_ctx *w; 687 688 if (params != NULL) { 689 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 690 "get_portal_groups requires no parameters"); 691 return; 692 } 693 694 w = spdk_jsonrpc_begin_result(request); 695 spdk_json_write_array_begin(w); 696 spdk_iscsi_portal_grps_info_json(w); 697 spdk_json_write_array_end(w); 698 699 spdk_jsonrpc_end_result(request, w); 700 } 701 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups, SPDK_RPC_RUNTIME) 702 703 struct rpc_portal { 704 char *host; 705 char *port; 706 char *cpumask; 707 }; 708 709 struct rpc_portal_list { 710 size_t num_portals; 711 struct rpc_portal portals[MAX_PORTAL]; 712 }; 713 714 struct rpc_portal_group { 715 int32_t tag; 716 struct rpc_portal_list portal_list; 717 }; 718 719 static void 720 free_rpc_portal(struct rpc_portal *portal) 721 { 722 free(portal->host); 723 free(portal->port); 724 free(portal->cpumask); 725 } 726 727 static void 728 free_rpc_portal_list(struct rpc_portal_list *pl) 729 { 730 size_t i; 731 732 for (i = 0; i < pl->num_portals; i++) { 733 free_rpc_portal(&pl->portals[i]); 734 } 735 pl->num_portals = 0; 736 } 737 738 static void 739 free_rpc_portal_group(struct rpc_portal_group *pg) 740 { 741 free_rpc_portal_list(&pg->portal_list); 742 } 743 744 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 745 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 746 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 747 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 748 }; 749 750 static int 751 decode_rpc_portal(const struct spdk_json_val *val, void *out) 752 { 753 struct rpc_portal *portal = out; 754 755 return spdk_json_decode_object(val, rpc_portal_decoders, 756 SPDK_COUNTOF(rpc_portal_decoders), 757 portal); 758 } 759 760 static int 761 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 762 { 763 struct rpc_portal_list *list = out; 764 765 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 766 sizeof(struct rpc_portal)); 767 } 768 769 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 770 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 771 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 772 }; 773 774 static void 775 spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request, 776 const struct spdk_json_val *params) 777 { 778 struct rpc_portal_group req = {}; 779 struct spdk_iscsi_portal_grp *pg = NULL; 780 struct spdk_iscsi_portal *portal; 781 struct spdk_json_write_ctx *w; 782 size_t i = 0; 783 int rc = -1; 784 785 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 786 SPDK_COUNTOF(rpc_portal_group_decoders), 787 &req)) { 788 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 789 goto out; 790 } 791 792 pg = spdk_iscsi_portal_grp_create(req.tag); 793 if (pg == NULL) { 794 SPDK_ERRLOG("portal_grp_create failed\n"); 795 goto out; 796 } 797 for (i = 0; i < req.portal_list.num_portals; i++) { 798 if (req.portal_list.portals[i].cpumask) { 799 SPDK_WARNLOG("A portal was specified with a CPU mask which is no longer supported.\n"); 800 SPDK_WARNLOG("Ignoring the cpumask.\n"); 801 } 802 803 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 804 req.portal_list.portals[i].port); 805 if (portal == NULL) { 806 SPDK_ERRLOG("portal_create failed\n"); 807 goto out; 808 } 809 spdk_iscsi_portal_grp_add_portal(pg, portal); 810 } 811 812 rc = spdk_iscsi_portal_grp_open(pg); 813 if (rc != 0) { 814 SPDK_ERRLOG("portal_grp_open failed\n"); 815 goto out; 816 } 817 818 rc = spdk_iscsi_portal_grp_register(pg); 819 if (rc != 0) { 820 SPDK_ERRLOG("portal_grp_register failed\n"); 821 } 822 823 out: 824 if (rc == 0) { 825 w = spdk_jsonrpc_begin_result(request); 826 spdk_json_write_bool(w, true); 827 spdk_jsonrpc_end_result(request, w); 828 } else { 829 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 830 831 if (pg != NULL) { 832 spdk_iscsi_portal_grp_release(pg); 833 } 834 } 835 free_rpc_portal_group(&req); 836 } 837 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group, SPDK_RPC_RUNTIME) 838 839 struct rpc_delete_portal_group { 840 int32_t tag; 841 }; 842 843 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 844 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 845 }; 846 847 static void 848 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request, 849 const struct spdk_json_val *params) 850 { 851 struct rpc_delete_portal_group req = {}; 852 struct spdk_json_write_ctx *w; 853 struct spdk_iscsi_portal_grp *pg; 854 855 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 856 SPDK_COUNTOF(rpc_delete_portal_group_decoders), 857 &req)) { 858 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 859 goto invalid; 860 } 861 862 pg = spdk_iscsi_portal_grp_unregister(req.tag); 863 if (!pg) { 864 goto invalid; 865 } 866 867 spdk_iscsi_tgt_node_delete_map(pg, NULL); 868 spdk_iscsi_portal_grp_release(pg); 869 870 w = spdk_jsonrpc_begin_result(request); 871 spdk_json_write_bool(w, true); 872 spdk_jsonrpc_end_result(request, w); 873 return; 874 875 invalid: 876 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 877 } 878 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group, SPDK_RPC_RUNTIME) 879 880 struct rpc_get_iscsi_connections_ctx { 881 struct spdk_jsonrpc_request *request; 882 struct spdk_json_write_ctx *w; 883 }; 884 885 static void 886 rpc_get_iscsi_connections_done(struct spdk_io_channel_iter *i, int status) 887 { 888 struct rpc_get_iscsi_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 889 890 spdk_json_write_array_end(ctx->w); 891 spdk_jsonrpc_end_result(ctx->request, ctx->w); 892 893 free(ctx); 894 } 895 896 static void 897 rpc_get_iscsi_connections(struct spdk_io_channel_iter *i) 898 { 899 struct rpc_get_iscsi_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 900 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 901 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 902 struct spdk_iscsi_conn *conn; 903 904 STAILQ_FOREACH(conn, &pg->connections, link) { 905 spdk_iscsi_conn_info_json(ctx->w, conn); 906 } 907 908 spdk_for_each_channel_continue(i, 0); 909 } 910 911 static void 912 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request, 913 const struct spdk_json_val *params) 914 { 915 struct rpc_get_iscsi_connections_ctx *ctx; 916 917 if (params != NULL) { 918 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 919 "get_iscsi_connections requires no parameters"); 920 return; 921 } 922 923 ctx = calloc(1, sizeof(struct rpc_get_iscsi_connections_ctx)); 924 if (ctx == NULL) { 925 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 926 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 927 return; 928 } 929 930 ctx->request = request; 931 ctx->w = spdk_jsonrpc_begin_result(request); 932 933 spdk_json_write_array_begin(ctx->w); 934 935 spdk_for_each_channel(&g_spdk_iscsi, 936 rpc_get_iscsi_connections, 937 ctx, 938 rpc_get_iscsi_connections_done); 939 } 940 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections, SPDK_RPC_RUNTIME) 941 942 struct rpc_target_lun { 943 char *name; 944 char *bdev_name; 945 int32_t lun_id; 946 }; 947 948 static void 949 free_rpc_target_lun(struct rpc_target_lun *req) 950 { 951 free(req->name); 952 free(req->bdev_name); 953 } 954 955 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 956 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 957 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 958 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 959 }; 960 961 static void 962 spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request, 963 const struct spdk_json_val *params) 964 { 965 struct rpc_target_lun req = {}; 966 struct spdk_json_write_ctx *w; 967 struct spdk_iscsi_tgt_node *target; 968 int rc; 969 970 req.lun_id = -1; 971 972 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 973 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 974 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 975 goto invalid; 976 } 977 978 target = spdk_iscsi_find_tgt_node(req.name); 979 if (target == NULL) { 980 SPDK_ERRLOG("target is not found\n"); 981 goto invalid; 982 } 983 984 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 985 if (rc < 0) { 986 SPDK_ERRLOG("add lun failed\n"); 987 goto invalid; 988 } 989 990 free_rpc_target_lun(&req); 991 992 w = spdk_jsonrpc_begin_result(request); 993 spdk_json_write_bool(w, true); 994 spdk_jsonrpc_end_result(request, w); 995 return; 996 997 invalid: 998 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 999 "Invalid parameters"); 1000 free_rpc_target_lun(&req); 1001 } 1002 SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME) 1003 1004 struct rpc_target_auth { 1005 char *name; 1006 bool disable_chap; 1007 bool require_chap; 1008 bool mutual_chap; 1009 int32_t chap_group; 1010 }; 1011 1012 static void 1013 free_rpc_target_auth(struct rpc_target_auth *req) 1014 { 1015 free(req->name); 1016 } 1017 1018 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1019 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1020 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1021 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1022 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1023 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1024 }; 1025 1026 static void 1027 spdk_rpc_set_iscsi_target_node_auth(struct spdk_jsonrpc_request *request, 1028 const struct spdk_json_val *params) 1029 { 1030 struct rpc_target_auth req = {}; 1031 struct spdk_json_write_ctx *w; 1032 struct spdk_iscsi_tgt_node *target; 1033 int rc; 1034 1035 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1036 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1037 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1038 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1039 "Invalid parameters"); 1040 goto exit; 1041 } 1042 1043 target = spdk_iscsi_find_tgt_node(req.name); 1044 if (target == NULL) { 1045 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1046 "Could not find target %s", req.name); 1047 goto exit; 1048 } 1049 1050 rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1051 req.mutual_chap, req.chap_group); 1052 if (rc < 0) { 1053 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1054 "Invalid combination of auth params"); 1055 goto exit; 1056 } 1057 1058 free_rpc_target_auth(&req); 1059 1060 w = spdk_jsonrpc_begin_result(request); 1061 spdk_json_write_bool(w, true); 1062 spdk_jsonrpc_end_result(request, w); 1063 return; 1064 1065 exit: 1066 free_rpc_target_auth(&req); 1067 } 1068 SPDK_RPC_REGISTER("set_iscsi_target_node_auth", spdk_rpc_set_iscsi_target_node_auth, 1069 SPDK_RPC_RUNTIME) 1070 1071 static void 1072 spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request, 1073 const struct spdk_json_val *params) 1074 { 1075 struct spdk_json_write_ctx *w; 1076 1077 if (params != NULL) { 1078 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1079 "get_iscsi_global_params requires no parameters"); 1080 return; 1081 } 1082 1083 w = spdk_jsonrpc_begin_result(request); 1084 spdk_iscsi_opts_info_json(w); 1085 1086 spdk_jsonrpc_end_result(request, w); 1087 } 1088 SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME) 1089 1090 struct rpc_discovery_auth { 1091 bool disable_chap; 1092 bool require_chap; 1093 bool mutual_chap; 1094 int32_t chap_group; 1095 }; 1096 1097 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1098 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1099 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1100 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1101 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1102 }; 1103 1104 static void 1105 spdk_rpc_set_iscsi_discovery_auth(struct spdk_jsonrpc_request *request, 1106 const struct spdk_json_val *params) 1107 { 1108 struct rpc_discovery_auth req = {}; 1109 struct spdk_json_write_ctx *w; 1110 int rc; 1111 1112 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1113 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1114 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1115 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1116 "Invalid parameters"); 1117 return; 1118 } 1119 1120 rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1121 req.mutual_chap, req.chap_group); 1122 if (rc < 0) { 1123 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1124 "Invalid combination of CHAP params"); 1125 return; 1126 } 1127 1128 w = spdk_jsonrpc_begin_result(request); 1129 spdk_json_write_bool(w, true); 1130 spdk_jsonrpc_end_result(request, w); 1131 } 1132 SPDK_RPC_REGISTER("set_iscsi_discovery_auth", spdk_rpc_set_iscsi_discovery_auth, SPDK_RPC_RUNTIME) 1133 1134 1135 #define MAX_AUTH_SECRETS 64 1136 1137 struct rpc_auth_secret { 1138 char *user; 1139 char *secret; 1140 char *muser; 1141 char *msecret; 1142 }; 1143 1144 static void 1145 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1146 { 1147 free(_secret->user); 1148 free(_secret->secret); 1149 free(_secret->muser); 1150 free(_secret->msecret); 1151 } 1152 1153 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1154 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1155 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1156 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1157 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1158 }; 1159 1160 static int 1161 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1162 { 1163 struct rpc_auth_secret *_secret = out; 1164 1165 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1166 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1167 } 1168 1169 struct rpc_auth_secrets { 1170 size_t num_secret; 1171 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1172 }; 1173 1174 static void 1175 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1176 { 1177 size_t i; 1178 1179 for (i = 0; i < secrets->num_secret; i++) { 1180 free_rpc_auth_secret(&secrets->secrets[i]); 1181 } 1182 } 1183 1184 static int 1185 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1186 { 1187 struct rpc_auth_secrets *secrets = out; 1188 1189 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1190 MAX_AUTH_SECRETS, &secrets->num_secret, 1191 sizeof(struct rpc_auth_secret)); 1192 } 1193 1194 struct rpc_auth_group { 1195 int32_t tag; 1196 struct rpc_auth_secrets secrets; 1197 }; 1198 1199 static void 1200 free_rpc_auth_group(struct rpc_auth_group *group) 1201 { 1202 free_rpc_auth_secrets(&group->secrets); 1203 } 1204 1205 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1206 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1207 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1208 }; 1209 1210 static void 1211 spdk_rpc_add_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1212 const struct spdk_json_val *params) 1213 { 1214 struct rpc_auth_group req = {}; 1215 struct rpc_auth_secret *_secret; 1216 struct spdk_json_write_ctx *w; 1217 struct spdk_iscsi_auth_group *group = NULL; 1218 int rc; 1219 size_t i; 1220 1221 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1222 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1223 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1224 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1225 "Invalid parameters"); 1226 free_rpc_auth_group(&req); 1227 return; 1228 } 1229 1230 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1231 1232 rc = spdk_iscsi_add_auth_group(req.tag, &group); 1233 if (rc != 0) { 1234 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1235 1236 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1237 "Could not add auth group (%d), %s", 1238 req.tag, spdk_strerror(-rc)); 1239 free_rpc_auth_group(&req); 1240 return; 1241 } 1242 1243 for (i = 0; i < req.secrets.num_secret; i++) { 1244 _secret = &req.secrets.secrets[i]; 1245 rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1246 _secret->muser, _secret->msecret); 1247 if (rc != 0) { 1248 spdk_iscsi_delete_auth_group(group); 1249 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1250 1251 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1252 "Could not add secret to auth group (%d), %s", 1253 req.tag, spdk_strerror(-rc)); 1254 free_rpc_auth_group(&req); 1255 return; 1256 } 1257 } 1258 1259 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1260 1261 free_rpc_auth_group(&req); 1262 1263 w = spdk_jsonrpc_begin_result(request); 1264 spdk_json_write_bool(w, true); 1265 spdk_jsonrpc_end_result(request, w); 1266 } 1267 SPDK_RPC_REGISTER("add_iscsi_auth_group", spdk_rpc_add_iscsi_auth_group, SPDK_RPC_RUNTIME) 1268 1269 struct rpc_delete_auth_group { 1270 int32_t tag; 1271 }; 1272 1273 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1274 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1275 }; 1276 1277 static void 1278 spdk_rpc_delete_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1279 const struct spdk_json_val *params) 1280 { 1281 struct rpc_delete_auth_group req = {}; 1282 struct spdk_json_write_ctx *w; 1283 struct spdk_iscsi_auth_group *group; 1284 1285 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1286 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1287 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1288 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1289 "Invalid parameters"); 1290 return; 1291 } 1292 1293 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1294 1295 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1296 if (group == NULL) { 1297 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1298 1299 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1300 "Could not find auth group (%d)", req.tag); 1301 return; 1302 } 1303 1304 spdk_iscsi_delete_auth_group(group); 1305 1306 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1307 1308 w = spdk_jsonrpc_begin_result(request); 1309 spdk_json_write_bool(w, true); 1310 spdk_jsonrpc_end_result(request, w); 1311 } 1312 SPDK_RPC_REGISTER("delete_iscsi_auth_group", spdk_rpc_delete_iscsi_auth_group, SPDK_RPC_RUNTIME) 1313 1314 struct rpc_add_auth_secret { 1315 int32_t tag; 1316 char *user; 1317 char *secret; 1318 char *muser; 1319 char *msecret; 1320 }; 1321 1322 static void 1323 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1324 { 1325 free(_secret->user); 1326 free(_secret->secret); 1327 free(_secret->muser); 1328 free(_secret->msecret); 1329 } 1330 1331 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1332 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1333 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1334 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1335 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1336 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1337 }; 1338 1339 static void 1340 spdk_rpc_add_secret_to_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1341 const struct spdk_json_val *params) 1342 { 1343 struct rpc_add_auth_secret req = {}; 1344 struct spdk_json_write_ctx *w; 1345 struct spdk_iscsi_auth_group *group; 1346 int rc; 1347 1348 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1349 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1350 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1351 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1352 "Invalid parameters"); 1353 free_rpc_add_auth_secret(&req); 1354 return; 1355 } 1356 1357 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1358 1359 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1360 if (group == NULL) { 1361 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1362 1363 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1364 "Could not find auth group (%d)", req.tag); 1365 free_rpc_add_auth_secret(&req); 1366 return; 1367 } 1368 1369 rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1370 if (rc != 0) { 1371 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1372 1373 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1374 "Could not add secret to auth group (%d), %s", 1375 req.tag, spdk_strerror(-rc)); 1376 free_rpc_add_auth_secret(&req); 1377 return; 1378 } 1379 1380 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1381 1382 free_rpc_add_auth_secret(&req); 1383 1384 w = spdk_jsonrpc_begin_result(request); 1385 spdk_json_write_bool(w, true); 1386 spdk_jsonrpc_end_result(request, w); 1387 } 1388 SPDK_RPC_REGISTER("add_secret_to_iscsi_auth_group", spdk_rpc_add_secret_to_iscsi_auth_group, 1389 SPDK_RPC_RUNTIME) 1390 1391 struct rpc_delete_auth_secret { 1392 int32_t tag; 1393 char *user; 1394 }; 1395 1396 static void 1397 free_rpc_delete_auth_secret(struct rpc_delete_auth_secret *_secret) 1398 { 1399 free(_secret->user); 1400 } 1401 1402 static const struct spdk_json_object_decoder rpc_delete_auth_secret_decoders[] = { 1403 {"tag", offsetof(struct rpc_delete_auth_secret, tag), spdk_json_decode_int32}, 1404 {"user", offsetof(struct rpc_delete_auth_secret, user), spdk_json_decode_string}, 1405 }; 1406 1407 static void 1408 spdk_rpc_delete_secret_from_iscsi_auth_group(struct spdk_jsonrpc_request *request, 1409 const struct spdk_json_val *params) 1410 { 1411 struct rpc_delete_auth_secret req = {}; 1412 struct spdk_json_write_ctx *w; 1413 struct spdk_iscsi_auth_group *group; 1414 int rc; 1415 1416 if (spdk_json_decode_object(params, rpc_delete_auth_secret_decoders, 1417 SPDK_COUNTOF(rpc_delete_auth_secret_decoders), &req)) { 1418 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1419 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1420 "Invalid parameters"); 1421 free_rpc_delete_auth_secret(&req); 1422 return; 1423 } 1424 1425 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1426 1427 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1428 if (group == NULL) { 1429 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1430 1431 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1432 "Could not find auth group (%d)", req.tag); 1433 free_rpc_delete_auth_secret(&req); 1434 return; 1435 } 1436 1437 rc = spdk_iscsi_auth_group_delete_secret(group, req.user); 1438 if (rc != 0) { 1439 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1440 1441 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1442 "Could not delete secret from CHAP group (%d), %s", 1443 req.tag, spdk_strerror(-rc)); 1444 free_rpc_delete_auth_secret(&req); 1445 return; 1446 } 1447 1448 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1449 1450 free_rpc_delete_auth_secret(&req); 1451 1452 w = spdk_jsonrpc_begin_result(request); 1453 spdk_json_write_bool(w, true); 1454 spdk_jsonrpc_end_result(request, w); 1455 } 1456 SPDK_RPC_REGISTER("delete_secret_from_iscsi_auth_group", 1457 spdk_rpc_delete_secret_from_iscsi_auth_group, SPDK_RPC_RUNTIME) 1458 1459 static void 1460 spdk_rpc_get_iscsi_auth_groups(struct spdk_jsonrpc_request *request, 1461 const struct spdk_json_val *params) 1462 { 1463 struct spdk_json_write_ctx *w; 1464 1465 if (params != NULL) { 1466 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1467 "get_iscsi_auth_groups requires no parameters"); 1468 return; 1469 } 1470 1471 w = spdk_jsonrpc_begin_result(request); 1472 spdk_json_write_array_begin(w); 1473 spdk_iscsi_auth_groups_info_json(w); 1474 spdk_json_write_array_end(w); 1475 1476 spdk_jsonrpc_end_result(request, w); 1477 } 1478 SPDK_RPC_REGISTER("get_iscsi_auth_groups", spdk_rpc_get_iscsi_auth_groups, SPDK_RPC_RUNTIME) 1479 1480 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1481 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1482 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1483 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1484 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1485 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1486 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1487 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1488 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1489 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1490 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1491 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1492 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1493 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1494 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1495 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1496 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1497 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1498 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1499 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1500 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1501 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1502 {"min_connections_per_core", offsetof(struct spdk_iscsi_opts, min_connections_per_core), spdk_json_decode_uint32, true}, 1503 }; 1504 1505 static void 1506 spdk_rpc_set_iscsi_options(struct spdk_jsonrpc_request *request, 1507 const struct spdk_json_val *params) 1508 { 1509 struct spdk_iscsi_opts *opts; 1510 struct spdk_json_write_ctx *w; 1511 1512 if (g_spdk_iscsi_opts != NULL) { 1513 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1514 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1515 "Must not call more than once"); 1516 return; 1517 } 1518 1519 opts = spdk_iscsi_opts_alloc(); 1520 if (opts == NULL) { 1521 SPDK_ERRLOG("spdk_iscsi_opts_alloc() failed.\n"); 1522 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1523 "Out of memory"); 1524 return; 1525 } 1526 1527 if (params != NULL) { 1528 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1529 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1530 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1531 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1532 "Invalid parameters"); 1533 spdk_iscsi_opts_free(opts); 1534 return; 1535 } 1536 } 1537 1538 g_spdk_iscsi_opts = spdk_iscsi_opts_copy(opts); 1539 spdk_iscsi_opts_free(opts); 1540 1541 if (g_spdk_iscsi_opts == NULL) { 1542 SPDK_ERRLOG("spdk_iscsi_opts_copy() failed\n"); 1543 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1544 "Out of memory"); 1545 return; 1546 } 1547 1548 w = spdk_jsonrpc_begin_result(request); 1549 spdk_json_write_bool(w, true); 1550 spdk_jsonrpc_end_result(request, w); 1551 } 1552 SPDK_RPC_REGISTER("set_iscsi_options", spdk_rpc_set_iscsi_options, SPDK_RPC_STARTUP) 1553